Search in sources :

Example 6 with GenericName

use of org.opengis.util.GenericName in project sis by apache.

the class CoordinateOperationMethods method writeIdentification.

/**
 * Writes identification info about the given method.
 * This method writes the following information:
 *
 * <ul>
 *   <li>EPSG codes</li>
 *   <li>Aliases</li>
 *   <li>Domain of validity</li>
 * </ul>
 */
private void writeIdentification(final OperationMethod method) throws IOException {
    final int table = openTag("table class=\"info\"");
    /*
         * ────────────────    EPSG IDENTIFIERS    ────────────────────────────────────
         */
    final StringBuilder buffer = new StringBuilder();
    for (final ReferenceIdentifier id : method.getIdentifiers()) {
        if (Constants.EPSG.equalsIgnoreCase(id.getCodeSpace())) {
            if (buffer.length() != 0) {
                buffer.append(", ");
            }
            final boolean isDeprecated = isDeprecated(id);
            if (isDeprecated) {
                buffer.append("<del>");
            }
            buffer.append(id.getCode());
            if (isDeprecated) {
                buffer.append("</del>");
            }
        }
    }
    if (buffer.length() != 0) {
        final int tr = openTag("tr");
        println("th", "EPSG code:");
        println("td", buffer);
        closeTags(tr);
    }
    /*
         * ────────────────    ALIASES    ─────────────────────────────────────────────
         */
    buffer.setLength(0);
    for (final GenericName alias : method.getAlias()) {
        if (buffer.length() != 0) {
            buffer.append(", ");
        }
        final GenericName head = alias.head();
        if (head == alias || Constants.EPSG.equalsIgnoreCase(head.toString())) {
            buffer.append(alias.tip());
        } else {
            buffer.append("<span class=\"non-epsg\">").append(head).append(":</span>").append("<code>").append(alias.tip()).append("</code>");
        }
    }
    if (buffer.length() != 0) {
        final int tr = openTag("tr");
        println("th", "Aliases:");
        println("td", buffer);
        closeTags(tr);
    }
    /*
         * ────────────────    DOMAIN OF VALIDITY    ──────────────────────────────────
         */
    buffer.setLength(0);
    final DefaultGeographicBoundingBox domain = getDomainOfValidity(method);
    if (domain != null) {
        openTag("tr");
        println("th", "Domain of validity:");
        println("td", buffer.append(new Latitude(domain.getSouthBoundLatitude())).append(" to ").append(new Latitude(domain.getNorthBoundLatitude())).append(" and ").append(new Longitude(domain.getWestBoundLongitude())).append(" to ").append(new Longitude(domain.getEastBoundLongitude())));
    }
    closeTags(table);
}
Also used : GenericName(org.opengis.util.GenericName) ReferenceIdentifier(org.opengis.referencing.ReferenceIdentifier) DefaultGeographicBoundingBox(org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox) Latitude(org.apache.sis.measure.Latitude) Longitude(org.apache.sis.measure.Longitude)

Example 7 with GenericName

use of org.opengis.util.GenericName in project sis by apache.

the class MetadataBuilder method addFeatureType.

/**
 * Adds descriptions for the given feature.
 * Storage location is:
 *
 * <ul>
 *   <li>{@code metadata/contentInfo/featureTypes/featureTypeName}</li>
 *   <li>{@code metadata/contentInfo/featureTypes/featureInstanceCount}</li>
 * </ul>
 *
 * This method returns the feature name for more convenient chaining with
 * {@link org.apache.sis.storage.FeatureNaming#add FeatureNaming.add(…)}.
 * Note that the {@link FeatureCatalogBuilder} subclasses can also be used for that chaining.
 *
 * @param  type         the feature type to add, or {@code null} for no-operation.
 * @param  occurrences  number of instances of the given feature type, or {@code null} if unknown.
 * @return the name of the added feature, or {@code null} if none.
 *
 * @see FeatureCatalogBuilder#define(DefaultFeatureType)
 */
public final GenericName addFeatureType(final DefaultFeatureType type, final Integer occurrences) {
    if (type != null) {
        final GenericName name = type.getName();
        if (name != null) {
            final DefaultFeatureTypeInfo info = new DefaultFeatureTypeInfo(name);
            if (occurrences != null) {
                info.setFeatureInstanceCount(shared(occurrences));
            }
            addIfNotPresent(featureDescription().getFeatureTypeInfo(), info);
            return name;
        }
    }
    return null;
}
Also used : GenericName(org.opengis.util.GenericName) DefaultFeatureTypeInfo(org.apache.sis.metadata.iso.content.DefaultFeatureTypeInfo)

Example 8 with GenericName

use of org.opengis.util.GenericName in project sis by apache.

the class AbstractOperation method toString.

/**
 * Returns a string representation of this operation.
 * The returned string is for debugging purpose and may change in any future SIS version.
 *
 * @return a string representation of this operation for debugging purpose.
 */
@Debug
@Override
public String toString() {
    final StringBuilder buffer = new StringBuilder(40).append(Classes.getShortClassName(this)).append('[');
    final GenericName name = getName();
    if (name != null) {
        buffer.append('“');
    }
    buffer.append(name);
    if (name != null) {
        buffer.append('”');
    }
    final AbstractIdentifiedType result = getResult();
    if (result != null) {
        final Object type;
        if (result instanceof DefaultAttributeType<?>) {
            type = Classes.getShortName(((DefaultAttributeType<?>) result).getValueClass());
        } else {
            type = result.getName();
        }
        buffer.append(" : ").append(type);
    }
    try {
        formatResultFormula(buffer.append("] = "));
    } catch (IOException e) {
        // Should never happen since we write in a StringBuilder.
        throw new UncheckedIOException(e);
    }
    return buffer.toString();
}
Also used : GenericName(org.opengis.util.GenericName) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) Debug(org.apache.sis.util.Debug)

Example 9 with GenericName

use of org.opengis.util.GenericName in project sis by apache.

the class DefaultFeatureType method computeTransientFields.

/**
 * Computes transient fields ({@link #assignableTo}, {@link #byName}, {@link #indices}, {@link #isSimple}).
 *
 * <p>As a side effect, this method checks for missing or duplicated names.</p>
 *
 * @param  properties  same content as {@link #properties} (may be the reference to the same list), but
 *         optionally in a temporarily modifiable list if we want to allow removal of duplicated values.
 *         See {@code scanPropertiesFrom(FeatureType, Collection)} javadoc for more explanation.
 * @throws IllegalArgumentException if two properties have the same name.
 */
private void computeTransientFields(final List<AbstractIdentifiedType> properties) {
    final int capacity = Containers.hashMapCapacity(properties.size());
    byName = new LinkedHashMap<>(capacity);
    indices = new LinkedHashMap<>(capacity);
    assignableTo = new HashSet<>(4);
    assignableTo.add(super.getName());
    scanPropertiesFrom(this, properties);
    allProperties = UnmodifiableArrayList.wrap(byName.values().toArray(new AbstractIdentifiedType[byName.size()]));
    /*
         * Now check if the feature is simple/complex or dense/sparse. We perform this check after we finished
         * to create the list of all properties, because some properties may be overridden and we want to take
         * in account only the most specific ones.
         */
    isSimple = true;
    int index = 0;
    // Count of mandatory properties.
    int mandatory = 0;
    for (final Map.Entry<String, AbstractIdentifiedType> entry : byName.entrySet()) {
        final int minimumOccurs, maximumOccurs;
        final AbstractIdentifiedType property = entry.getValue();
        if (property instanceof DefaultAttributeType<?>) {
            // Other SIS branches check for AttributeType instead.
            minimumOccurs = ((DefaultAttributeType<?>) property).getMinimumOccurs();
            maximumOccurs = ((DefaultAttributeType<?>) property).getMaximumOccurs();
            isSimple &= (minimumOccurs == maximumOccurs);
        } else if (property instanceof FieldType) {
            // TODO: check for AssociationRole instead (after GeoAPI upgrade).
            minimumOccurs = ((FieldType) property).getMinimumOccurs();
            maximumOccurs = ((FieldType) property).getMaximumOccurs();
            isSimple = false;
        } else {
            if (isParameterlessOperation(property)) {
                indices.put(entry.getKey(), OPERATION_INDEX);
            }
            // For feature operations, maximumOccurs is implicitly 0.
            continue;
        }
        if (maximumOccurs != 0) {
            isSimple &= (maximumOccurs == 1);
            indices.put(entry.getKey(), index++);
            if (minimumOccurs != 0) {
                mandatory++;
            }
        }
    }
    /*
         * If some properties use long name of the form "head:tip", creates short aliases containing only the "tip"
         * name for convenience, provided that it does not create ambiguity.  If a short alias could map to two or
         * more properties, then that alias is not added.
         *
         * In the 'aliases' map below, null values will be assigned to ambiguous short names.
         */
    final Map<String, AbstractIdentifiedType> aliases = new LinkedHashMap<>();
    for (final AbstractIdentifiedType property : allProperties) {
        GenericName name = property.getName();
        while (name instanceof ScopedName) {
            // Safety against broken implementations.
            if (name == (name = ((ScopedName) name).tail()))
                break;
            String key = name.toString();
            // Safety against broken implementations.
            if (key == null || (key = key.trim()).isEmpty())
                break;
            aliases.put(key, aliases.containsKey(key) ? null : property);
        }
    }
    for (final Map.Entry<String, AbstractIdentifiedType> entry : aliases.entrySet()) {
        final AbstractIdentifiedType property = entry.getValue();
        if (property != null) {
            final String tip = entry.getKey();
            if (byName.putIfAbsent(tip, property) == null) {
                /*
                     * This block is skipped if there is properties named "tip" and "head:tip".
                     * The 'indices' value may be null if the property is an operation.
                     */
                final Integer value = indices.get(property.getName().toString());
                if (value != null && indices.put(tip, value) != null) {
                    // Should never happen.
                    throw new AssertionError(tip);
                }
            }
        }
    }
    /*
         * Trim the collections. Especially useful when the collections have less that 2 elements.
         */
    byName = CollectionsExt.compact(byName);
    indices = CollectionsExt.compact(indices);
    assignableTo = CollectionsExt.unmodifiableOrCopy(assignableTo);
    /*
         * Rational for choosing whether the feature is sparse: By default, java.util.HashMap implementation creates
         * an internal array of length 16 (see HashMap.DEFAULT_INITIAL_CAPACITY).  In addition, the HashMap instance
         * itself consumes approximatively 8 "words" in memory.  Consequently there is no advantage in using HashMap
         * unless the number of properties is greater than 16 + 8 (note: we could specify a smaller initial capacity,
         * but the memory consumed by each internal Map.Entry quickly exceed the few saved words). Next, the default
         * HashMap threshold is 0.75, so there is again no advantage in using HashMap if we do not expect at least 25%
         * of unused properties. Our current implementation arbitrarily sets the threshold to 50%.
         */
    final int n = indices.size();
    isSparse = (n > 24) && (mandatory <= n / 2);
}
Also used : InternationalString(org.opengis.util.InternationalString) LinkedHashMap(java.util.LinkedHashMap) GenericName(org.opengis.util.GenericName) ScopedName(org.opengis.util.ScopedName) IdentityHashMap(java.util.IdentityHashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 10 with GenericName

use of org.opengis.util.GenericName in project sis by apache.

the class DefaultAssociationRoleTest method testCyclicAssociation.

/**
 * Tests {@code DefaultFeatureType.isAssignableFrom(FeatureType)} and {@code DefaultFeatureType.equals(Object)}
 * on a feature type having a bidirectional association to an other feature. This test will fall in an infinite
 * loop if the implementation does not have proper guard against infinite recursivity.
 */
@Test
@DependsOnMethod("testBidirectionalAssociation")
public void testCyclicAssociation() {
    final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
    final GenericName nameOfA = factory.createTypeName(null, "A");
    final GenericName nameOfB = factory.createTypeName(null, "B");
    final GenericName nameOfC = factory.createTypeName(null, "C");
    final GenericName nameOfD = factory.createTypeName(null, "D");
    /*
         * Associations defined only by the FeatureType name.
         */
    final DefaultAssociationRole toB = new DefaultAssociationRole(singletonMap(NAME_KEY, "toB"), nameOfB, 1, 1);
    final DefaultAssociationRole toC = new DefaultAssociationRole(singletonMap(NAME_KEY, "toC"), nameOfC, 1, 1);
    final DefaultAssociationRole toD = new DefaultAssociationRole(singletonMap(NAME_KEY, "toD"), nameOfD, 1, 1);
    final DefaultFeatureType typeA = createType(nameOfA, null, toB);
    final DefaultFeatureType typeB = createType(nameOfB, null, toC);
    final DefaultFeatureType typeC = createType(nameOfC, null, toD);
    /*
         * Association defined with real FeatureType instance, except for an association to itself.
         * Construction of this FeatureType shall cause the resolution of all above FeatureTypes.
         */
    final DefaultAssociationRole toAr = new DefaultAssociationRole(singletonMap(NAME_KEY, "toA"), typeA, 1, 1);
    final DefaultAssociationRole toBr = new DefaultAssociationRole(singletonMap(NAME_KEY, toB.getName()), typeB, 1, 1);
    final DefaultAssociationRole toCr = new DefaultAssociationRole(singletonMap(NAME_KEY, toC.getName()), typeC, 1, 1);
    final DefaultFeatureType typeD = createType(nameOfD, null, toAr, toBr, toCr, toD);
    /*
         * Verify the property given to the constructors. There is no reason for those properties
         * to change as they are not the instances to be replaced by the name resolutions, but we
         * verify them as a paranoiac check.
         */
    assertSame("A.properties", toB, getSingleton(typeA.getProperties(false)));
    assertSame("B.properties", toC, getSingleton(typeB.getProperties(false)));
    assertSame("C.properties", toD, getSingleton(typeC.getProperties(false)));
    assertSame("D.properties", toAr, typeD.getProperty("toA"));
    assertSame("D.properties", toBr, typeD.getProperty("toB"));
    assertSame("D.properties", toCr, typeD.getProperty("toC"));
    assertSame("D.properties", toD, typeD.getProperty("toD"));
    /*
         * CORE OF THIS TEST: verify that the values of toB, toC and toD have been replaced by the actual
         * FeatureType instances. Also verify that as a result, toB.equals(toBr) and toC.equals(toCr).
         */
    assertSame("toA", typeA, toAr.getValueType());
    assertSame("toB", typeB, toBr.getValueType());
    assertSame("toB", typeB, toB.getValueType());
    assertSame("toC", typeC, toCr.getValueType());
    assertSame("toC", typeC, toC.getValueType());
    assertSame("toD", typeD, toD.getValueType());
    assertEquals("toB", toB, toBr);
    assertEquals("toC", toC, toCr);
    /*
         * Other equality tests, mostly for verifying that we do not fall in an infinite loop here.
         */
    assertFalse("equals", typeA.equals(typeD));
    assertFalse("equals", typeD.equals(typeA));
    assertFalse("equals", typeB.equals(typeC));
    assertFalse("equals", typeC.equals(typeB));
    assertFalse("hashCode", typeA.hashCode() == typeB.hashCode());
    assertFalse("hashCode", typeC.hashCode() == typeD.hashCode());
}
Also used : GenericName(org.opengis.util.GenericName) NameFactory(org.opengis.util.NameFactory) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Aggregations

GenericName (org.opengis.util.GenericName)46 Test (org.junit.Test)11 ReferenceIdentifier (org.opengis.referencing.ReferenceIdentifier)9 InternationalString (org.opengis.util.InternationalString)9 ArrayList (java.util.ArrayList)5 IdentifiedObject (org.opengis.referencing.IdentifiedObject)5 NameFactory (org.opengis.util.NameFactory)5 Identifier (org.opengis.metadata.Identifier)4 ScopedName (org.opengis.util.ScopedName)4 HashMap (java.util.HashMap)3 DependsOnMethod (org.apache.sis.test.DependsOnMethod)3 IOException (java.io.IOException)2 UncheckedIOException (java.io.UncheckedIOException)2 Collection (java.util.Collection)2 IdentityHashMap (java.util.IdentityHashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 Map (java.util.Map)2 AbstractIdentifiedType (org.apache.sis.feature.AbstractIdentifiedType)2 NameToIdentifier (org.apache.sis.internal.metadata.NameToIdentifier)2 TableAppender (org.apache.sis.io.TableAppender)2