Search in sources :

Example 1 with DefaultFeatureType

use of org.apache.sis.feature.DefaultFeatureType in project sis by apache.

the class FeatureTypeBuilderTest method testAddAnonymousIdentifier.

/**
 * Tests {@link FeatureTypeBuilder#addAttribute(Class)} where one attribute is an identifier that already has
 * the {@code "sis:identifier"} name. This is called "anonymous" because identifiers with an explicit name in
 * the data file should use that name instead in the feature type.
 */
@Test
@DependsOnMethod("testAddIdentifierAndGeometry")
public void testAddAnonymousIdentifier() {
    final FeatureTypeBuilder builder = new FeatureTypeBuilder();
    assertSame(builder, builder.setName("City"));
    builder.addAttribute(String.class).setName(AttributeConvention.IDENTIFIER_PROPERTY).addRole(AttributeRole.IDENTIFIER_COMPONENT);
    builder.addAttribute(Integer.class).setName("population");
    final DefaultFeatureType type = builder.build();
    final Iterator<? extends AbstractIdentifiedType> it = type.getProperties(true).iterator();
    final AbstractIdentifiedType a0 = it.next();
    final AbstractIdentifiedType a1 = it.next();
    assertFalse("properties count", it.hasNext());
    assertEquals("name", AttributeConvention.IDENTIFIER_PROPERTY, a0.getName());
    assertEquals("type", String.class, ((DefaultAttributeType<?>) a0).getValueClass());
    assertEquals("name", "population", a1.getName().toString());
    assertEquals("type", Integer.class, ((DefaultAttributeType<?>) a1).getValueClass());
}
Also used : DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) AbstractIdentifiedType(org.apache.sis.feature.AbstractIdentifiedType) DefaultFeatureTypeTest(org.apache.sis.feature.DefaultFeatureTypeTest) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 2 with DefaultFeatureType

use of org.apache.sis.feature.DefaultFeatureType in project sis by apache.

the class FeatureTypeBuilderTest method testAddAttribute.

/**
 * Tests {@link FeatureTypeBuilder#addAttribute(Class)}.
 */
@Test
@DependsOnMethod("testInitialization")
public void testAddAttribute() {
    final FeatureTypeBuilder builder = new FeatureTypeBuilder();
    assertSame(builder, builder.setName("myScope", "myName"));
    assertSame(builder, builder.setDefinition("test definition"));
    assertSame(builder, builder.setDesignation("test designation"));
    assertSame(builder, builder.setDescription("test description"));
    assertSame(builder, builder.setAbstract(true));
    builder.addAttribute(String.class).setName("name");
    builder.addAttribute(Integer.class).setName("age");
    builder.addAttribute(Point.class).setName("location").setCRS(HardCodedCRS.WGS84);
    builder.addAttribute(Double.class).setName("score").setDefaultValue(10.0).setMinimumOccurs(5).setMaximumOccurs(50);
    final DefaultFeatureType type = builder.build();
    assertEquals("name", "myScope:myName", type.getName().toString());
    assertEquals("definition", "test definition", type.getDefinition().toString());
    assertEquals("description", "test description", type.getDescription().toString());
    assertEquals("designation", "test designation", type.getDesignation().toString());
    assertTrue("isAbstract", type.isAbstract());
    final Iterator<? extends AbstractIdentifiedType> it = type.getProperties(true).iterator();
    final DefaultAttributeType<?> a0 = (DefaultAttributeType<?>) it.next();
    final DefaultAttributeType<?> a1 = (DefaultAttributeType<?>) it.next();
    final DefaultAttributeType<?> a2 = (DefaultAttributeType<?>) it.next();
    final DefaultAttributeType<?> a3 = (DefaultAttributeType<?>) it.next();
    assertFalse("properties count", it.hasNext());
    assertEquals("name", "name", a0.getName().toString());
    assertEquals("name", "age", a1.getName().toString());
    assertEquals("name", "location", a2.getName().toString());
    assertEquals("name", "score", a3.getName().toString());
    assertEquals("valueClass", String.class, a0.getValueClass());
    assertEquals("valueClass", Integer.class, a1.getValueClass());
    assertEquals("valueClass", Point.class, a2.getValueClass());
    assertEquals("valueClass", Double.class, a3.getValueClass());
    assertEquals("minimumOccurs", 1, a0.getMinimumOccurs());
    assertEquals("minimumOccurs", 1, a1.getMinimumOccurs());
    assertEquals("minimumOccurs", 1, a2.getMinimumOccurs());
    assertEquals("minimumOccurs", 5, a3.getMinimumOccurs());
    assertEquals("maximumOccurs", 1, a0.getMaximumOccurs());
    assertEquals("maximumOccurs", 1, a1.getMaximumOccurs());
    assertEquals("maximumOccurs", 1, a2.getMaximumOccurs());
    assertEquals("maximumOccurs", 50, a3.getMaximumOccurs());
    assertEquals("defaultValue", null, a0.getDefaultValue());
    assertEquals("defaultValue", null, a1.getDefaultValue());
    assertEquals("defaultValue", null, a2.getDefaultValue());
    assertEquals("defaultValue", 10.0, a3.getDefaultValue());
    assertFalse("characterizedByCRS", AttributeConvention.characterizedByCRS(a0));
    assertFalse("characterizedByCRS", AttributeConvention.characterizedByCRS(a1));
    assertTrue("characterizedByCRS", AttributeConvention.characterizedByCRS(a2));
    assertFalse("characterizedByCRS", AttributeConvention.characterizedByCRS(a3));
}
Also used : DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) DefaultAttributeType(org.apache.sis.feature.DefaultAttributeType) DefaultFeatureTypeTest(org.apache.sis.feature.DefaultFeatureTypeTest) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 3 with DefaultFeatureType

use of org.apache.sis.feature.DefaultFeatureType in project sis by apache.

the class FeatureTypeBuilderTest method testBuildCache.

/**
 * Verifies that {@code build()} method returns the previously created instance when possible.
 * See {@link AttributeTypeBuilder#build()} javadoc for a rational.
 */
@Test
@DependsOnMethod("testAddAttribute")
public void testBuildCache() {
    final FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("City");
    final DefaultAttributeType<String> name = builder.addAttribute(String.class).setName("name").build();
    final DefaultFeatureType city = builder.build();
    assertSame("Should return the existing AttributeType.", name, city.getProperty("name"));
    assertSame("Should return the existing FeatureType.", city, builder.build());
    assertSame("Should return the existing AttributeType since we didn't changed anything.", name, builder.getProperty("name").build());
    assertNotSame("Should return a new AttributeType since we changed something.", name, builder.getProperty("name").setDescription("Name of the city").build());
    assertNotSame("Should return a new FeatureType since we changed an attribute.", city, builder.build());
}
Also used : DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) DefaultFeatureTypeTest(org.apache.sis.feature.DefaultFeatureTypeTest) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 4 with DefaultFeatureType

use of org.apache.sis.feature.DefaultFeatureType in project sis by apache.

the class FeatureTypeBuilderTest method testAddAnonymousGeometry.

/**
 * Tests {@link FeatureTypeBuilder#addAttribute(Class)} where one attribute is a geometry that already has
 * the {@code "sis:geometry"} name. This is called "anonymous" because geometries with an explicit name in
 * the data file should use that name instead in the feature type.
 */
@Test
@DependsOnMethod("testAddIdentifierAndGeometry")
public void testAddAnonymousGeometry() {
    final FeatureTypeBuilder builder = new FeatureTypeBuilder();
    assertSame(builder, builder.setName("City"));
    builder.addAttribute(Point.class).setName(AttributeConvention.GEOMETRY_PROPERTY).addRole(AttributeRole.DEFAULT_GEOMETRY);
    builder.addAttribute(Integer.class).setName("population");
    final DefaultFeatureType type = builder.build();
    final Iterator<? extends AbstractIdentifiedType> it = type.getProperties(true).iterator();
    final AbstractIdentifiedType a0 = it.next();
    final AbstractIdentifiedType a1 = it.next();
    final AbstractIdentifiedType a2 = it.next();
    assertFalse("properties count", it.hasNext());
    assertEquals("name", AttributeConvention.ENVELOPE_PROPERTY, a0.getName());
    assertEquals("name", AttributeConvention.GEOMETRY_PROPERTY, a1.getName());
    assertEquals("type", Point.class, ((DefaultAttributeType<?>) a1).getValueClass());
    assertEquals("name", "population", a2.getName().toString());
    assertEquals("type", Integer.class, ((DefaultAttributeType<?>) a2).getValueClass());
}
Also used : DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) AbstractIdentifiedType(org.apache.sis.feature.AbstractIdentifiedType) DefaultFeatureTypeTest(org.apache.sis.feature.DefaultFeatureTypeTest) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 5 with DefaultFeatureType

use of org.apache.sis.feature.DefaultFeatureType in project sis by apache.

the class FeatureTypeBuilder method build.

/**
 * Builds the feature type from the information and properties specified to this builder.
 * One of the {@code setName(…)} methods must have been invoked before this {@code build()} method (mandatory).
 * All other methods are optional, but some calls to a {@code add} method are usually needed.
 *
 * <div class="warning"><b>Warning:</b> In a future SIS version, the return type may be changed to the
 * {@code org.opengis.feature.FeatureType} interface. This change is pending GeoAPI revision.</div>
 *
 * <p>If a feature type has already been built and this builder state has not changed since the
 * feature type creation, then the previously created {@code FeatureType} instance is returned.</p>
 *
 * @return the feature type.
 * @throws IllegalStateException if the builder contains inconsistent information.
 *
 * @see #clear()
 */
@Override
public DefaultFeatureType build() throws IllegalStateException {
    if (feature == null) {
        /*
             * Creates an initial array of property types with up to 3 slots reserved for sis:identifier, sis:geometry
             * and sis:envelope operations. At first we presume that there is always an identifier. The identifier slot
             * will be removed later if there is none.
             */
        // Number of explicitely specified properties.
        final int numSpecified = properties.size();
        // Number of synthetic properties that may be generated.
        int numSynthetic;
        int envelopeIndex = -1;
        int geometryIndex = -1;
        final AbstractIdentifiedType[] identifierTypes;
        if (identifierCount == 0) {
            numSynthetic = 0;
            identifierTypes = null;
        } else {
            numSynthetic = 1;
            identifierTypes = new AbstractIdentifiedType[identifierCount];
        }
        if (defaultGeometry != null) {
            envelopeIndex = numSynthetic++;
            if (!AttributeConvention.GEOMETRY_PROPERTY.equals(defaultGeometry.getName())) {
                geometryIndex = numSynthetic++;
            }
        }
        final AbstractIdentifiedType[] propertyTypes = new AbstractIdentifiedType[numSynthetic + numSpecified];
        int propertyCursor = numSynthetic;
        int identifierCursor = 0;
        for (int i = 0; i < numSpecified; i++) {
            final PropertyTypeBuilder builder = properties.get(i);
            final AbstractIdentifiedType instance = builder.build();
            propertyTypes[propertyCursor] = instance;
            /*
                 * Collect the attributes to use as identifier components while we loop over all properties.
                 * A NullPointerException or an ArrayIndexOutOfBoundsException in this block would mean that
                 * identifierCount field has not been updated correctly by an addRole(AttributeRole) method.
                 */
            if (builder.isIdentifier()) {
                identifierTypes[identifierCursor++] = instance;
            }
            /*
                 * If there is a default geometry, add a link named "sis:geometry" to that geometry.
                 * It may happen that the property created by the user is already named "sis:geometry",
                 * in which case we will avoid to duplicate the property.
                 */
            if (builder == defaultGeometry && geometryIndex >= 0) {
                if (propertyTypes[geometryIndex] != null) {
                    /*
                         * Assuming that there is no bug in our implementation, this error could happen if the user
                         * has modified this FeatureTypeBuilder in another thread during this build() execution.
                         */
                    throw new CorruptedObjectException();
                }
                propertyTypes[geometryIndex] = FeatureOperations.link(name(AttributeConvention.GEOMETRY_PROPERTY), instance);
            }
            propertyCursor++;
        }
        /*
             * Create the "envelope" operation only after we created all other properties.
             * Actually it is okay if the 'propertyTypes' array still contains null elements not needed for envelope calculation
             * like "sis:identifier", since FeatureOperations.envelope(…) constructor ignores any property which is not for a value.
             */
        if (envelopeIndex >= 0)
            try {
                propertyTypes[envelopeIndex] = FeatureOperations.envelope(name(AttributeConvention.ENVELOPE_PROPERTY), null, propertyTypes);
            } catch (FactoryException e) {
                throw new IllegalStateException(e);
            }
        /*
             * If a synthetic identifier need to be created, create it now as the first property.
             * It may happen that the user provided a single identifier component already named
             * "sis:identifier", in which case we avoid to duplicate the property.
             */
        if (identifierTypes != null) {
            if (identifierCursor != identifierTypes.length) {
                /*
                     * Assuming that there is no bug in our implementation, this error could happen if the user
                     * has modified this FeatureTypeBuilder in another thread during this build() execution.
                     */
                throw new CorruptedObjectException();
            }
            if (AttributeConvention.IDENTIFIER_PROPERTY.equals(identifierTypes[0].getName())) {
                if (identifierCursor > 1) {
                    throw new IllegalStateException(Resources.format(Resources.Keys.PropertyAlreadyExists_2, getDisplayName(), AttributeConvention.IDENTIFIER_PROPERTY));
                }
                System.arraycopy(propertyTypes, 1, propertyTypes, 0, --propertyCursor);
            } else {
                propertyTypes[0] = FeatureOperations.compound(name(AttributeConvention.IDENTIFIER_PROPERTY), idDelimiter, idPrefix, idSuffix, identifierTypes);
            }
        }
        feature = new DefaultFeatureType(identification(), isAbstract(), superTypes.toArray(new DefaultFeatureType[superTypes.size()]), ArraysExt.resize(propertyTypes, propertyCursor));
    }
    return feature;
}
Also used : FactoryException(org.opengis.util.FactoryException) DefaultFeatureType(org.apache.sis.feature.DefaultFeatureType) CorruptedObjectException(org.apache.sis.util.CorruptedObjectException) AbstractIdentifiedType(org.apache.sis.feature.AbstractIdentifiedType)

Aggregations

DefaultFeatureType (org.apache.sis.feature.DefaultFeatureType)13 Test (org.junit.Test)10 DefaultFeatureTypeTest (org.apache.sis.feature.DefaultFeatureTypeTest)9 DependsOnMethod (org.apache.sis.test.DependsOnMethod)7 AbstractIdentifiedType (org.apache.sis.feature.AbstractIdentifiedType)4 Geometry (com.esri.core.geometry.Geometry)2 DefaultAttributeType (org.apache.sis.feature.DefaultAttributeType)2 Point (com.esri.core.geometry.Point)1 Collection (java.util.Collection)1 AbstractOperation (org.apache.sis.feature.AbstractOperation)1 IllegalFeatureTypeException (org.apache.sis.storage.IllegalFeatureTypeException)1 CorruptedObjectException (org.apache.sis.util.CorruptedObjectException)1 Envelope (org.opengis.geometry.Envelope)1 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)1 FactoryException (org.opengis.util.FactoryException)1