if (!isModifiable()) { unmodifiable = this; if (unmodifiable == null || !equals(unmodifiable)) { final ModifiableMetadata candidate = (ModifiableMetadata) MetadataCopier.forModifiable(getStandard()).copy(this); candidate.freeze(); assert !unmodifiable.isModifiable(); return unmodifiable;
/** * Returns an unmodifiable copy of the given metadata, if necessary and possible. */ private static Object unmodifiable(final Object metadata) { if (metadata instanceof ModifiableMetadata) { return ((ModifiableMetadata) metadata).unmodifiable(); } else { return metadata; } }
assert collectionType(elementType).isInstance(c); return c.isEmpty() && emptyCollectionAsNull() ? null : c; if (emptyCollectionAsNull()) { return null; final boolean isModifiable = isModifiable(); if (useSet(elementType)) { if (isModifiable) { return createSet(elementType, INITIAL_CAPACITY); } else { return Collections.emptySet();
/** * Returns the specified set, or a new one if {@code c} is null. * This is a convenience method for implementation of {@code getFoo()} methods. * * @param <E> the type represented by the {@code Class} argument. * @param c the existing set, or {@code null} if the set has not yet been created. * @param elementType the element type (used only if {@code c} is null). * @return {@code c}, or a new set if {@code c} is null. */ protected final <E> Set<E> nonNullSet(final Set<E> c, final Class<E> elementType) { if (c != null) { return c.isEmpty() && emptyCollectionAsNull() ? null : c; } if (emptyCollectionAsNull()) { return null; } if (isModifiable()) { return createSet(elementType, INITIAL_CAPACITY); } return Collections.emptySet(); }
/** * Returns the specified set, or a new one if {@code c} is null. * This is a convenience method for implementation of {@code getFoo()} methods. * * @param <E> the type represented by the {@code Class} argument. * @param current the existing set, or {@code null} if the set has not yet been created. * @param elementType the element type (used only if {@code c} is null). * @return {@code c}, or a new set if {@code c} is null. */ protected final <E> Set<E> nonNullSet(final Set<E> current, final Class<E> elementType) { if (current != null) { return current.isEmpty() && emptyCollectionAsNull() ? null : current; } if (emptyCollectionAsNull()) { return null; } if (state < FREEZING) { return createSet(elementType, null); } return Collections.emptySet(); }
/** * Creates a list or set with the content of the {@code source} collection, * or returns {@code null} if the source is {@code null} or empty. * This is a convenience method for copying fields in subclass copy constructors. * * <p>The collection type is selected as described in the * {@link #nonNullCollection(Collection, Class)}.</p> * * @param <E> the type represented by the {@code Class} argument. * @param source the source collection, or {@code null}. * @param elementType the base type of elements to put in the collection. * @return a collection containing the {@code source} elements, * or {@code null} if the source was null or empty. */ protected final <E> Collection<E> copyCollection(final Collection<? extends E> source, final Class<E> elementType) { if (isNullOrEmpty(source)) { return null; } final Collection<E> target; if (useSet(elementType)) { target = createSet(elementType, source); } else { target = createList(elementType, source); } target.addAll(source); return target; }
assert collectionType(elementType).isInstance(source); return (Collection<E>) source; checkWritePermission(); if (isNullOrEmpty(source)) { target = null; } else { final int capacity = source.size(); if (useSet(elementType)) { target = createSet(elementType, capacity); } else { target = new CheckedArrayList<>(elementType, capacity);
if (unmodifiable == null || (unmodifiable != this && unmodifiable != FREEZING && !equals(unmodifiable))) { final ModifiableMetadata candidate; try { candidate = clone(); } catch (CloneNotSupportedException exception) { return this; candidate.freeze(); assert !unmodifiable.isModifiable(); return unmodifiable;
final MetadataStandard standard = target.getStandard(); if (!standard.getInterface(source.getClass()).isInstance(target)) { return false; final Map<String,Object> targetMap = target.asMap(); final Map<String,Object> sourceMap; if (source instanceof AbstractMetadata) { name(target, propertyName), ((ModifiableMetadata) targetValue).getInterface(), Classes.getClass(sourceValue)));
/** * Creates a singleton list or set containing only the given value, if non-null. * This is a convenience method for initializing fields in subclass constructors. * * <p>The collection type is selected as described in the * {@link #nonNullCollection(Collection, Class)}.</p> * * @param <E> the type represented by the {@code Class} argument. * @param value the singleton value to put in the returned collection, or {@code null}. * @param elementType the element type (used only if {@code value} is non-null). * @return a new modifiable collection containing the given value, * or {@code null} if the given value was null. */ protected final <E> Collection<E> singleton(final E value, final Class<E> elementType) { if (value == null) { return null; } final Collection<E> collection; if (useSet(elementType)) { collection = createSet(elementType, INITIAL_CAPACITY); } else { collection = new CheckedArrayList<>(elementType, 1); } collection.add(value); return collection; }
/** * Declares this metadata and all its properties as unmodifiable. Any attempt to modify a property * after this method call will throw an {@link org.apache.sis.metadata.UnmodifiableMetadataException}. * If this metadata is already unmodifiable, then this method does nothing. * * <p>Subclasses usually do not need to override this method since the default implementation * performs most of its work using Java reflection.</p> */ @Override public void freeze() { if (isModifiable()) { final Collection<Identifier> p = identifiers; super.freeze(); /* * The 'identifiers' collection will have been replaced by an unmodifiable collection if * subclass has an "identifiers" property. If this is not the case, then the collection * is unchanged (or null) so we have to make it unmodifiable here. */ if (p == identifiers) { identifiers = CollectionsExt.unmodifiableOrCopy(p); // Null safe. } } }
/** * Returns the specified list, or a new one if {@code c} is null. * This is a convenience method for implementation of {@code getFoo()} methods. * * @param <E> the type represented by the {@code Class} argument. * @param c the existing list, or {@code null} if the list has not yet been created. * @param elementType the element type (used only if {@code c} is null). * @return {@code c}, or a new list if {@code c} is null. */ protected final <E> List<E> nonNullList(final List<E> c, final Class<E> elementType) { if (c != null) { return c.isEmpty() && emptyCollectionAsNull() ? null : c; } if (emptyCollectionAsNull()) { return null; } if (isModifiable()) { /* * Do not specify an initial capacity, because the list will stay empty in a majority of cases * (i.e. the users will want to iterate over the list elements more often than they will want * to add elements). JDK implementation of ArrayList has a lazy instantiation mechanism for * initially empty lists, but as of JDK8 this lazy instantiation works only for list having * the default capacity. */ return new CheckedArrayList<>(elementType); } return Collections.emptyList(); }
/** * Checks if changes in the metadata are allowed. All {@code setFoo(…)} methods in subclasses * shall invoke this method (directly or indirectly) before to apply any change. * The current property value should be specified in argument. * * @param current the current value, or {@code null} if none. * @throws UnmodifiableMetadataException if this metadata is unmodifiable. * * @see #state() * * @since 1.0 */ protected void checkWritePermission(Object current) throws UnmodifiableMetadataException { if (state != COMPLETABLE) { checkWritePermission(); } else if (current != null) { final MetadataStandard standard; if (current instanceof AbstractMetadata) { standard = ((AbstractMetadata) current).getStandard(); } else { standard = getStandard(); } final Object c = standard.getTitle(current); if (c != null) current = c; throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.ElementAlreadyInitialized_1, current)); } }
/** * Returns {@code true} if we should use a {@link Set} instead than a {@link List} * for elements of the given type. */ private <E> boolean useSet(final Class<E> elementType) { final Class<? extends Collection<E>> type = collectionType(elementType); if (Set .class == (Class) type) return true; if (List.class == (Class) type) return false; throw new NoSuchElementException(Errors.format(Errors.Keys.UnsupportedType_1, type)); }
return (List<E>) source; checkWritePermission(); if (isNullOrEmpty(source)) { target = null;
/** * Returns the specified list, or a new one if {@code c} is null. * This is a convenience method for implementation of {@code getFoo()} methods. * * @param <E> the type represented by the {@code Class} argument. * @param current the existing list, or {@code null} if the list has not yet been created. * @param elementType the element type (used only if {@code c} is null). * @return {@code c}, or a new list if {@code c} is null. */ protected final <E> List<E> nonNullList(final List<E> current, final Class<E> elementType) { if (current != null) { return current.isEmpty() && emptyCollectionAsNull() ? null : current; } if (emptyCollectionAsNull()) { return null; } if (state < FREEZING) { /* * Do not specify an initial capacity, because the list will stay empty in a majority of cases * (i.e. the users will want to iterate over the list elements more often than they will want * to add elements). JDK implementation of ArrayList has a lazy instantiation mechanism for * initially empty lists, but as of JDK8 this lazy instantiation works only for list having * the default capacity. */ return new CheckedArrayList<>(elementType); } return Collections.emptyList(); }
/** * Creates a set with the content of the {@code source} collection, * or returns {@code null} if the source is {@code null} or empty. * This is a convenience method for copying fields in subclass copy constructors. * * @param <E> the type represented by the {@code Class} argument. * @param source the source collection, or {@code null}. * @param elementType the base type of elements to put in the set. * @return a set containing the {@code source} elements, * or {@code null} if the source was null or empty. */ protected final <E> Set<E> copySet(final Collection<? extends E> source, final Class<E> elementType) { if (isNullOrEmpty(source)) { return null; } final Set<E> target = createSet(elementType, source); target.addAll(source); return target; }
/** * Creates a list with the content of the {@code source} collection, * or returns {@code null} if the source is {@code null} or empty. * This is a convenience method for copying fields in subclass copy constructors. * * @param <E> the type represented by the {@code Class} argument. * @param source the source collection, or {@code null}. * @param elementType the base type of elements to put in the list. * @return a list containing the {@code source} elements, * or {@code null} if the source was null or empty. */ protected final <E> List<E> copyList(final Collection<? extends E> source, final Class<E> elementType) { if (isNullOrEmpty(source)) { return null; } final List<E> target = createList(elementType, source); target.addAll(source); return target; }
assert (useSet != null) || collectionType(elementType).isInstance(source) : elementType; return (Collection<E>) source; checkWritePermission(valueIfDefined(target)); if (isNullOrEmpty(source)) { target = null; } else { if (useSet == null) { useSet = useSet(elementType); target = createSet(elementType, source); } else { target = createList(elementType, source);
final MetadataStandard standard = target.getStandard(); if (!standard.getInterface(source.getClass()).isInstance(target)) { return false; final Map<String,Object> targetMap = target.asMap(); final Map<String,Object> sourceMap; if (source instanceof AbstractMetadata) { name(target, propertyName), ((ModifiableMetadata) targetValue).getInterface(), Classes.getClass(sourceValue)));