blob: a2560fc6d937937effc7dbcdfe212883de0be1e5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.feature;
import java.util.Collection;
import java.util.Iterator;
import org.apache.sis.util.Deprecable;
import org.apache.sis.util.resources.Errors;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.feature.Property;
import org.opengis.feature.PropertyType;
import org.opengis.feature.MultiValuedPropertyException;
import org.opengis.feature.InvalidPropertyValueException;
/**
* Base class of property that can be stored in a {@link AbstractFeature} instance.
* This include {@code Attribute} and {@code Association}, but not {@code Operation}.
*
* @author Martin Desruisseaux (Geomatys)
*
* @param <V> the type of property values.
*/
abstract class Field<V> implements Property {
/**
* For subclass constructors.
*/
Field() {
}
/**
* Returns {@code true} if an attribute type or association role having the given
* maximum number of occurrences should be treated as a singleton.
*
* This method gives us a simple keyword to search for every places in the code
* where a decision regarding "singleton versus multi-valued" is made.
*/
static boolean isSingleton(final int maximumOccurs) {
return maximumOccurs <= 1;
}
/**
* Returns the field feature or attribute value, or {@code null} if none.
*
* @return the feature or attribute value (may be {@code null}).
* @throws MultiValuedPropertyException if this field contains more than one value.
*
* @see AbstractFeature#getPropertyValue(String)
*/
@Override
public abstract V getValue() throws MultiValuedPropertyException;
/**
* Returns all features or attribute values, or an empty collection if none.
* The returned collection is <em>live</em>: changes in the returned collection
* will be reflected immediately in this {@code Field} instance, and conversely.
*
* @return the features or attribute values in a <em>live</em> collection.
*/
public Collection<V> getValues() {
return new PropertySingleton<>(this);
}
/**
* Sets the feature or attribute value. All previous values are replaced by the given singleton.
*
* @param value the new value, or {@code null} for removing all values from this field.
*
* @see AbstractFeature#setPropertyValue(String, Object)
*/
public abstract void setValue(final V value);
/**
* Sets the features or attribute values. All previous values are replaced by the given collection.
*
* <p>The default implementation ensures that the given collection contains at most one element,
* then delegates to {@link #setValue(Object)}.</p>
*
* @param values the new values.
* @throws InvalidPropertyValueException if the given collection contains too many elements.
*/
public void setValues(final Collection<? extends V> values) throws InvalidPropertyValueException {
V value = null;
final Iterator<? extends V> it = values.iterator();
if (it.hasNext()) {
value = it.next();
if (it.hasNext()) {
throw new InvalidPropertyValueException(Errors.format(Errors.Keys.TooManyOccurrences_2, 1, getName()));
}
}
setValue(value);
}
/**
* Returns whether the given property is deprecated.
*/
static boolean isDeprecated(final PropertyType type) {
return (type instanceof Deprecable) && ((Deprecable) type).isDeprecated();
}
}