Search in sources :

Example 1 with AttributeTypeBuilder

use of org.apache.sis.feature.builder.AttributeTypeBuilder in project geotoolkit by Geomatys.

the class JAXBFeatureTypeReader method getType.

private Object getType(String namespaceURI, ComplexType type, BuildStack stack, boolean useCache) {
    final GenericName name = extractFinalName(namespaceURI, type);
    if (useCache && typesCache.containsKey(name)) {
        return typesCache.get(name);
    }
    for (XSDMapping.Spi mapping : mappings) {
        final XSDMapping map = mapping.create(name, this, type);
        if (map != null) {
            IdentifiedType mappedType = map.getType();
            if (mappedType instanceof AttributeType) {
                AttributeType at = (AttributeType) mappedType;
                AttributeTypeBuilder atb = new FeatureTypeBuilder().addAttribute(at);
                atb.addCharacteristic(XSDMapping.class).setName(GMLConvention.MAPPING).setDefaultValue(map);
                mappedType = atb.build();
            // AttributeType[] att = (AttributeType[]) at.characteristics().values().toArray(new AttributeType[0]);
            // final Map properties = new HashMap();
            // properties.put(AbstractIdentifiedType.NAME_KEY, at.getName());
            // properties.put(AbstractIdentifiedType.DEFINITION_KEY, at.getDefinition());
            // properties.put(AbstractIdentifiedType.DEPRECATED_KEY, ((Deprecable) at).isDeprecated());
            // properties.put(AbstractIdentifiedType.DESCRIPTION_KEY, at.getDescription());
            // properties.put(AbstractIdentifiedType.DESIGNATION_KEY, at.getDesignation());
            // mappedType = new MappedAttributeType(
            // properties,
            // at.getValueClass(),
            // at.getMinimumOccurs(),
            // at.getMaximumOccurs(),
            // at.getDefaultValue(),
            // map,
            // att);
            }
            typesCache.put(name, mappedType);
            return mappedType;
        }
    }
    // special case for gml:ReferenceType
    final String namespace = NamesExt.getNamespace(name);
    if ((GMLConvention.GML_311_NAMESPACE.equals(namespace) || GMLConvention.GML_321_NAMESPACE.equals(namespace)) && "ReferenceType".equals(name.tip().toString())) {
        // note : can't use real AbstractGMLType, recursive object creation
        final QName gml = new QName(namespace, "AbstractGMLType");
        final Object abstractGmlType = getType(gml, stack);
        if (abstractGmlType instanceof GenericName) {
            final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
            FeatureAssociationRole far = ftb.addAssociation((GenericName) abstractGmlType).setName(name).build();
            typesCache.put(name, far);
            return far;
        } else {
            final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
            FeatureAssociationRole far = ftb.addAssociation((FeatureType) abstractGmlType).setName(name).build();
            typesCache.put(name, far);
            return far;
        }
    }
    final boolean deprecated = GMLConvention.isDeprecated(type);
    // read simple content type if defined
    final SimpleContent simpleContent = type.getSimpleContent();
    if (simpleContent != null) {
        final ExtensionType sext = simpleContent.getExtension();
        if (sext != null) {
            // simple type base, it must be : this is the content of the tag <tag>XXX<tag>
            // it is not named, so we call it value
            final QName base = sext.getBase();
            final AttributeType st = (AttributeType) resolveType(base, stack);
            final AttributeTypeBuilder atb = new FeatureTypeBuilder().addAttribute(st);
            atb.setName(name);
            atb.setDeprecated(deprecated);
            // read attributes
            for (PropertyType property : getAnnotatedAttributes(namespaceURI, sext.getAttributeOrAttributeGroup(), stack)) {
                CharacteristicTypeBuilder cb = atb.getCharacteristic(property.getName().toString());
                if (cb == null) {
                    atb.addCharacteristic((AttributeType) property);
                } else {
                // characteristic already exist
                }
            }
            final AttributeType att = atb.build();
            typesCache.put(name, att);
            return att;
        }
        final SimpleRestrictionType restriction = simpleContent.getRestriction();
        if (restriction != null) {
            final QName base = restriction.getBase();
            if (base != null) {
                final ComplexType sct = xsdContext.findComplexType(base);
                if (sct != null) {
                    final AttributeType tct = (AttributeType) getType(namespaceURI, sct, stack, true);
                    final AttributeTypeBuilder atb = new FeatureTypeBuilder().addAttribute(tct);
                    atb.setName(name);
                    atb.setDeprecated(deprecated);
                    // read attributes
                    for (PropertyType property : getAnnotatedAttributes(namespaceURI, restriction.getAttributeOrAttributeGroup(), stack)) {
                        CharacteristicTypeBuilder cb = atb.getCharacteristic(property.getName().toString());
                        if (cb == null) {
                            atb.addCharacteristic((AttributeType) property);
                        } else {
                        // characteristic already exist
                        }
                    }
                    final AttributeType att = atb.build();
                    typesCache.put(name, att);
                    return att;
                } else {
                // final PropertyType restType = resolveType(base, stack);
                // addOrReplace(finalType.builder, atb.create(restType, NamesExt.create(namespaceURI, Utils.VALUE_PROPERTY_NAME), 0, 1, false, null));
                }
            }
        }
        throw new MismatchedFeatureException("Undefined simple type : " + name);
    }
    final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
    ftb.setName(name);
    ftb.setDeprecated(deprecated);
    // read attributes
    for (PropertyType property : getAnnotatedAttributes(namespaceURI, type.getAttributeOrAttributeGroup(), stack)) {
        addProperty(ftb, property);
    }
    // read sequence properties
    for (PropertyType property : getGroupAttributes(namespaceURI, type.getSequence(), stack)) {
        addProperty(ftb, property);
    }
    // read complex content if defined
    final ComplexContent content = type.getComplexContent();
    if (content != null) {
        final ExtensionType extension = content.getExtension();
        if (extension != null) {
            final QName base = extension.getBase();
            if (base != null && !base.getLocalPart().equalsIgnoreCase("anytype")) {
                final Object parent = getType(base, stack);
                if (parent instanceof FeatureType) {
                    ftb.setSuperTypes((FeatureType) parent);
                } else if (parent instanceof GenericName) {
                    // parent type is currently being resolved
                    return name;
                }
            }
            // read attributes
            for (PropertyType property : getAnnotatedAttributes(namespaceURI, extension.getAttributeOrAttributeGroup(), stack)) {
                addProperty(ftb, property);
            }
            // read groups
            for (PropertyType property : getGroupAttributes(namespaceURI, extension.getSequence(), stack)) {
                addProperty(ftb, property);
            }
        }
        /* BIG DIRTY HACK: Needed for GML 2.1.2 support.
             * For geometry definition, GML 2 propose an association to some
             * data-type defined by restiction over an abstract geometry type.
             * But, we do not want it to an association, we want it to be an
             * attribute, for god sake ! So, we cheat and if we find a structure
             * like that, we transform it into attribute (oh god that's awful).
             */
        final ComplexRestrictionType restriction = content.getRestriction();
        if (restriction != null) {
            final QName base = restriction.getBase();
            if (base != null) {
                Object restrictionType = getType(base, stack);
                if (restrictionType instanceof FeatureType) {
                    ftb.setSuperTypes((FeatureType) restrictionType);
                }
            // final ComplexType sct = xsdContext.findComplexType(base);
            // if (sct != null) {
            // final Object obj = getType(base.getNamespaceURI(), sct, stack);
            // if (obj instanceof FeatureType
            // //                                && isGeometric((FeatureType)obj)
            // ) {
            // final ExplicitGroup sequence = sct.getSequence();
            // if (sequence != null) {
            // final List<Element> elements = sequence.getElements();
            // if (elements != null && !elements.isEmpty()) {
            // Element e = sequence.getElements().get(0);
            // return ftb.addAttribute(Geometry.class)
            // .setName(e.getRef().getLocalPart())
            // .setMinimumOccurs(sequence.getMinOccurs())
            // .build();
            // }
            // }
            // } else if (obj instanceof PropertyType) {
            // final PropertyTypeBuilder ptb = new FeatureTypeBuilder().addProperty((PropertyType) obj);
            // if (ptb instanceof PropertyTypeBuilder) {
            // final AttributeTypeBuilder atb = (AttributeTypeBuilder) ptb;
            // // check characteristics
            // for (PropertyType property : getAnnotatedAttributes(namespaceURI, restriction.getAttributeOrAttributeGroup(), stack)) {
            // if (atb.getCharacteristic(property.getName().toString()) == null) {
            // atb.addCharacteristic((AttributeType) property);
            // }
            // }
            // }
            // }
            // }
            }
        }
    }
    // read choice if set
    final ExplicitGroup choice = type.getChoice();
    if (choice != null) {
    // this is the case of gml:location
    }
    // //        if (GMLConvention.isDecoratedProperty(featureType.getName().tip().toString())) {
    // //            //Used by geometry property types but also in some gml profils
    // //            final String decoratedName = NamesExt.toExpandedString(featureType.getName());
    // //
    // //            //this is an encapsulated property, we unroll it
    // //            final Collection<? extends PropertyType> subProps = featureType.getProperties(true);
    // //            //we peek the first association, there should be only one
    // //            //but attributes are possible
    // //            for (PropertyType pt : subProps) {
    // //                if (pt.getName().tip().toString().startsWith("@")) {
    // //                    //ignore xml attributes
    // //                    continue;
    // //                }
    // //
    // //                if (pt instanceof FeatureAssociationRole) {
    // //                    /* HACK : GML 3.1.1 : Only way I've found to manage
    // //                     * geometries as attributes. If we've found an association,
    // //                     * and if it's feature type is a geometric property
    // //                     * (derived from abstract geometric type), well, we
    // //                     * return a geometric property.
    // //                     */
    // //                    final FeatureAssociationRole subFar = (FeatureAssociationRole) pt;
    // //                    FeatureType valueType = subFar.getValueType();
    // //                    FeatureAssociationRole ar = ftb
    // //                            .addAssociation(subFar)
    // //                            .setDescription(GMLConvention.DECORATED_DESCRIPTION+NamesExt.toExpandedString(subFar.getName()))
    // //                            .build();
    // //
    // //                    typesCache.put(name, ar);
    // //                    return featureType;
    // //                } else if (pt instanceof AttributeType) {
    // //                    AttributeType at = (AttributeType) pt;
    // //
    // //                    ftb.clear();
    // //                    at = ftb.addAttribute(at).setDescription(GMLConvention.DECORATED_DESCRIPTION+" "+NamesExt.toExpandedString(at.getName())).build();
    // //                    typesCache.put(name, at);
    // //                    return at;
    // //                }
    // //            }
    // //
    // //            throw new UnsupportedOperationException("Decorated property without any property");
    // //
    // //        }
    // define the default geometry
    PropertyTypeBuilder candidateDefaultGeom = null;
    for (PropertyTypeBuilder ptb : ftb.properties()) {
        if (ptb instanceof AttributeTypeBuilder) {
            Class valueClass = ((AttributeTypeBuilder) ptb).getValueClass();
            if (Geometry.class.isAssignableFrom(valueClass)) {
                XSDMapping mapping = GMLConvention.getMapping(ptb.build());
                if (mapping instanceof GeometryMapping) {
                    if (((GeometryMapping) mapping).isDecorated()) {
                        // keep it as a candidate, we prefere undecorated properties
                        candidateDefaultGeom = ptb;
                    } else {
                        candidateDefaultGeom = null;
                        ((AttributeTypeBuilder) ptb).addRole(AttributeRole.DEFAULT_GEOMETRY);
                        break;
                    }
                }
            }
        }
    }
    if (candidateDefaultGeom != null) {
        ((AttributeTypeBuilder) candidateDefaultGeom).addRole(AttributeRole.DEFAULT_GEOMETRY);
    }
    FeatureType featureType = ftb.build();
    typesCache.put(name, featureType);
    return featureType;
}
Also used : GeometryMapping(org.geotoolkit.feature.xml.jaxb.mapping.GeometryMapping) SimpleRestrictionType(org.geotoolkit.xsd.xml.v2001.SimpleRestrictionType) FeatureType(org.opengis.feature.FeatureType) XSDMapping(org.geotoolkit.feature.xml.jaxb.mapping.XSDMapping) PropertyType(org.opengis.feature.PropertyType) ComplexContent(org.geotoolkit.xsd.xml.v2001.ComplexContent) ExplicitGroup(org.geotoolkit.xsd.xml.v2001.ExplicitGroup) SingleAttributeTypeBuilder(org.geotoolkit.feature.SingleAttributeTypeBuilder) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) PropertyTypeBuilder(org.apache.sis.feature.builder.PropertyTypeBuilder) GenericName(org.opengis.util.GenericName) AttributeType(org.opengis.feature.AttributeType) IdentifiedType(org.opengis.feature.IdentifiedType) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) QName(javax.xml.namespace.QName) ComplexRestrictionType(org.geotoolkit.xsd.xml.v2001.ComplexRestrictionType) CharacteristicTypeBuilder(org.apache.sis.feature.builder.CharacteristicTypeBuilder) MismatchedFeatureException(org.opengis.feature.MismatchedFeatureException) ExtensionType(org.geotoolkit.xsd.xml.v2001.ExtensionType) SimpleContent(org.geotoolkit.xsd.xml.v2001.SimpleContent) FeatureAssociationRole(org.opengis.feature.FeatureAssociationRole) LocalComplexType(org.geotoolkit.xsd.xml.v2001.LocalComplexType) ComplexType(org.geotoolkit.xsd.xml.v2001.ComplexType)

Example 2 with AttributeTypeBuilder

use of org.apache.sis.feature.builder.AttributeTypeBuilder in project geotoolkit by Geomatys.

the class XmlFeatureTypeTest method testReadWfsFeatureType.

@Test
public void testReadWfsFeatureType() throws JAXBException {
    final JAXBFeatureTypeReader reader = getReader(true);
    final List<FeatureType> types = new ArrayList<>(reader.read(XmlFeatureTypeTest.class.getResourceAsStream("/org/geotoolkit/feature/xml/wfs1.xsd")).getValues());
    removeGMLBaseTypes(types);
    assertEquals(1, types.size());
    final String ns = "http://mapserver.gis.umn.edu/mapserver";
    final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
    ftb.setName(ns, "quadrige");
    ftb.setSuperTypes(GMLConvention.ABSTRACTFEATURETYPE_31);
    AttributeTypeBuilder atb = ftb.addAttribute(Geometry.class).setName(ns, "msGeometry").setMinimumOccurs(0).setMaximumOccurs(1);
    atb.addCharacteristic(NILLABLE_CHARACTERISTIC).setDefaultValue(true);
    atb.addRole(AttributeRole.DEFAULT_GEOMETRY);
    ftb.addAttribute(String.class).setName(ns, "C_SIEPT38").setMinimumOccurs(1).setMaximumOccurs(1);
    ftb.addAttribute(String.class).setName(ns, "L_SIEPT").setMinimumOccurs(1).setMaximumOccurs(1);
    final FeatureType wfsType = ftb.build();
    FeatureComparator comparator = new FeatureComparator(wfsType, types.get(0));
    comparator.ignoredCharacteristics.add("http://www.w3.org/1999/xlink:href");
    comparator.ignoredCharacteristics.add("http://www.w3.org/2001/XMLSchema-instance:@nil");
    comparator.ignoredCharacteristics.add("mapping");
    comparator.compare();
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) FeatureType(org.opengis.feature.FeatureType) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) ArrayList(java.util.ArrayList) JAXBFeatureTypeReader(org.geotoolkit.feature.xml.jaxb.JAXBFeatureTypeReader) FeatureComparator(org.apache.sis.test.feature.FeatureComparator)

Example 3 with AttributeTypeBuilder

use of org.apache.sis.feature.builder.AttributeTypeBuilder in project geotoolkit by Geomatys.

the class ShapefileFeatureStore method createFeatureType.

// //////////////////////////////////////////////////////////////////////////
// schema manipulation /////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////
/**
 * Set the FeatureType of this DataStore. This method will delete any
 * existing local resources or throw an IOException if the featurestore is
 * remote.
 *
 * @param featureType The desired FeatureType.
 * @throws DataStoreException If the featurestore is remote.
 *
 * @todo must synchronize this properly
 */
@Override
public void createFeatureType(final FeatureType featureType) throws DataStoreException {
    final GenericName typeName = featureType.getName();
    if (!isWritable(typeName.toString())) {
        throw new DataStoreException("Read-only acces prevent type creation.");
    }
    if (typeName == null) {
        throw new DataStoreException("Type name can not be null.");
    }
    if (!featureType.isSimple()) {
        throw new DataStoreException("Feature type must not be null and must be a simple feature type.");
    }
    if (!featureType.getName().equals(typeName)) {
        throw new DataStoreException("Shapefile featurestore can only hold typename same as feature type name.");
    }
    try {
        // delete the files
        shpFiles.delete();
    } catch (IOException ex) {
        throw new DataStoreException("Cannot reset datastore content", ex);
    }
    final AccessManager locker = shpFiles.createLocker();
    // update schema and name
    name = typeName;
    schema = featureType;
    AttributeType desc;
    try {
        desc = Features.toAttribute(FeatureExt.getDefaultGeometry(featureType)).orElse(null);
    } catch (PropertyNotFoundException e) {
        getLogger().log(Level.FINE, e, () -> String.format("No geometry can be found in given datatype%n%s", featureType));
        desc = null;
    }
    CoordinateReferenceSystem crs = null;
    final Class<?> geomType;
    final ShapeType shapeType;
    if (desc != null) {
        crs = FeatureExt.getCRS(desc);
        geomType = desc.getValueClass();
        shapeType = ShapeType.findBestGeometryType(geomType);
    } else {
        geomType = null;
        shapeType = ShapeType.NULL;
    }
    if (shapeType == ShapeType.UNDEFINED) {
        throw new DataStoreException("Cannot create a shapefile whose geometry type is " + geomType);
    }
    try (Closeable disposeLocker = locker::disposeReaderAndWriters) {
        final StorageFile shpStoragefile = locker.getStorageFile(SHP);
        final StorageFile shxStoragefile = locker.getStorageFile(SHX);
        final StorageFile dbfStoragefile = locker.getStorageFile(DBF);
        final StorageFile prjStoragefile = locker.getStorageFile(PRJ);
        final StorageFile cpgStoragefile = locker.getStorageFile(CPG);
        try (FileChannel shpChannel = shpStoragefile.getWriteChannel();
            FileChannel shxChannel = shxStoragefile.getWriteChannel()) {
            try (ShapefileWriter writer = new ShapefileWriter(shpChannel, shxChannel)) {
                // try to get the domain first
                final Envelope domain = CRS.getDomainOfValidity(crs);
                if (domain != null) {
                    writer.writeHeaders(new JTSEnvelope2D(domain), shapeType, 0, 100);
                } else {
                    // try to reproject the single overall envelope keeping poles out of the way
                    final JTSEnvelope2D env = new JTSEnvelope2D(-179, 179, -89, 89, CommonCRS.WGS84.normalizedGeographic());
                    JTSEnvelope2D transformedBounds;
                    if (crs != null) {
                        try {
                            transformedBounds = env.transform(crs);
                        } catch (Exception t) {
                            getLogger().log(Level.WARNING, t.getLocalizedMessage(), t);
                            // It can happen for local projections :
                            transformedBounds = new JTSEnvelope2D(crs);
                        }
                    } else {
                        transformedBounds = env;
                    }
                    writer.writeHeaders(transformedBounds, shapeType, 0, 100);
                }
            }
        }
        final DbaseFileHeader dbfheader = DbaseFileHeader.createDbaseHeader(schema);
        dbfheader.setNumRecords(0);
        try (WritableByteChannel dbfChannel = dbfStoragefile.getWriteChannel()) {
            dbfheader.writeHeader(dbfChannel);
        }
        if (crs != null) {
            // .prj files should have no carriage returns in them, this messes up
            // ESRI's ArcXXX software, so we'll be compatible
            final WKTFormat format = new WKTFormat(Locale.ENGLISH, null);
            format.setConvention(Convention.WKT1_COMMON_UNITS);
            format.setNameAuthority(Citations.ESRI);
            format.setIndentation(WKTFormat.SINGLE_LINE);
            final String s = format.format(crs);
            IOUtilities.writeString(s, prjStoragefile.getFile(), Charset.forName("ISO-8859-1"));
        } else {
            getLogger().warning("PRJ file not generated for null CoordinateReferenceSystem");
            Path prjFile = prjStoragefile.getFile();
            Files.deleteIfExists(prjFile);
        }
        // write dbf encoding .cpg
        CpgFiles.write(dbfCharset, cpgStoragefile.getFile());
    } catch (IOException ex) {
        throw new DataStoreException(ex);
    }
    // Once all writings have succeeded, we can commit them
    try {
        locker.replaceStorageFiles();
    } catch (IOException e) {
        throw new DataStoreException("Failed commiting file changes", e);
    }
    // force reading it again since the file type may be a little different
    name = null;
    schema = null;
    // we still preserve the original type name and attribute classes which may be more restricted
    final FeatureTypeBuilder ftb = new FeatureTypeBuilder(getFeatureType());
    ftb.setName(typeName);
    final AttributeTypeBuilder gtb = (AttributeTypeBuilder) ftb.getProperty("the_geom");
    if (Geometry.class.equals(gtb.getValueClass())) {
        gtb.setValueClass(shapeType.bestJTSClass());
    }
    gtb.setName(desc.getName());
    for (PropertyType pt : featureType.getProperties(true)) {
        if (pt instanceof AttributeType) {
            final AttributeType at = (AttributeType) pt;
            if (!Geometry.class.isAssignableFrom(at.getValueClass())) {
                try {
                    ((AttributeTypeBuilder) ftb.getProperty(at.getName().toString())).setValueClass(at.getValueClass()).setName(at.getName());
                } catch (PropertyNotFoundException ex) {
                }
            }
        }
    }
    schema = ftb.build();
    name = schema.getName();
}
Also used : AccessManager(org.geotoolkit.data.shapefile.lock.AccessManager) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) Closeable(java.io.Closeable) PropertyType(org.opengis.feature.PropertyType) Envelope(org.opengis.geometry.Envelope) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) GenericName(org.opengis.util.GenericName) AttributeType(org.opengis.feature.AttributeType) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) WKTFormat(org.apache.sis.io.wkt.WKTFormat) Path(java.nio.file.Path) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) DataStoreException(org.apache.sis.storage.DataStoreException) FileChannel(java.nio.channels.FileChannel) ShapeType(org.geotoolkit.data.shapefile.shp.ShapeType) WritableByteChannel(java.nio.channels.WritableByteChannel) IOException(java.io.IOException) DataStoreException(org.apache.sis.storage.DataStoreException) FeatureStoreRuntimeException(org.geotoolkit.storage.feature.FeatureStoreRuntimeException) UnsupportedQueryException(org.apache.sis.storage.UnsupportedQueryException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) Geometry(org.locationtech.jts.geom.Geometry) JTSEnvelope2D(org.geotoolkit.geometry.jts.JTSEnvelope2D) StorageFile(org.geotoolkit.data.shapefile.lock.StorageFile) ShapefileWriter(org.geotoolkit.data.shapefile.shp.ShapefileWriter)

Example 4 with AttributeTypeBuilder

use of org.apache.sis.feature.builder.AttributeTypeBuilder in project geotoolkit by Geomatys.

the class DefaultJDBCFeatureStore method createFeatureType.

// //////////////////////////////////////////////////////////////////////////
// Schema manipulation /////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////
/**
 * Complexe feature types will be decomposed in flat types then relations
 * will be rebuilded.
 */
@Override
public void createFeatureType(final FeatureType featureType) throws DataStoreException {
    ensureOpen();
    final GenericName typeName = featureType.getName();
    if (getNames().contains(typeName)) {
        throw new DataStoreException("Type name " + typeName + " already exists.");
    }
    Connection cnx = null;
    Statement stmt = null;
    String sql = null;
    final List<FeatureType> flatTypes = new ArrayList<>();
    final List<TypeRelation> relations = new ArrayList<>();
    try {
        cnx = getDataSource().getConnection();
        cnx.setAutoCommit(false);
        stmt = cnx.createStatement();
        // we must first decompose the feature type in flat types, then recreate relations
        decompose(featureType, flatTypes, relations);
        // rebuild flat types
        for (FeatureType flatType : flatTypes) {
            sql = getQueryBuilder().createTableSQL(flatType, cnx);
            stmt.execute(sql);
            dialect.postCreateTable(getDatabaseSchema(), flatType, cnx);
        }
        // rebuild relations
        if (!relations.isEmpty()) {
            // refresh the model to find primary keys
            dbmodel.clearCache();
            for (TypeRelation relation : relations) {
                final String propertyName = relation.property.getName().tip().toString();
                FeatureAssociationRole result = (FeatureAssociationRole) relation.property;
                final int minOccurs = result.getMinimumOccurs();
                final int maxOccurs = result.getMaximumOccurs();
                if (maxOccurs <= 1) {
                    // place relation on the children with a unique constraint
                    final AttributeTypeBuilder atb = new FeatureTypeBuilder().addAttribute(Integer.class);
                    atb.setName(propertyName);
                    final SQLQueryBuilder b = getQueryBuilder();
                    final String addColumn = b.alterTableAddColumnSQL(relation.child, atb.build(), cnx);
                    stmt.execute(addColumn);
                    final String addForeignKey = b.alterTableAddForeignKey(relation.child, propertyName, relation.parent.getName(), "fid", true);
                    stmt.execute(addForeignKey);
                    final String addUnique = b.alterTableAddIndex(relation.child, atb.getName().tip().toString());
                    stmt.execute(addUnique);
                } else {
                    // place relation on the children
                    final AttributeTypeBuilder atb = new FeatureTypeBuilder().addAttribute(Integer.class);
                    atb.setName(propertyName);
                    final SQLQueryBuilder b = getQueryBuilder();
                    final String addColumn = b.alterTableAddColumnSQL(relation.child, atb.build(), cnx);
                    stmt.execute(addColumn);
                    final String addForeignKey = b.alterTableAddForeignKey(relation.child, propertyName, relation.parent.getName(), "fid", true);
                    stmt.execute(addForeignKey);
                }
            }
        }
        cnx.commit();
    } catch (SQLException ex) {
        if (cnx != null) {
            try {
                cnx.rollback();
            } catch (SQLException ex1) {
                getLogger().log(Level.WARNING, ex1.getMessage(), ex1);
            }
        }
        throw new DataStoreException("Failed to create table " + typeName.tip() + "," + ex.getMessage() + "\n Query: " + sql, ex);
    } finally {
        JDBCFeatureStoreUtilities.closeSafe(getLogger(), cnx, stmt, null);
    }
    // reset the type name cache, will be recreated when needed.
    dbmodel.clearCache();
}
Also used : FeatureType(org.opengis.feature.FeatureType) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) DataStoreException(org.apache.sis.storage.DataStoreException) SQLException(java.sql.SQLException) Statement(java.sql.Statement) Connection(java.sql.Connection) ArrayList(java.util.ArrayList) SQLQueryBuilder(org.geotoolkit.db.dialect.SQLQueryBuilder) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) GenericName(org.opengis.util.GenericName) FeatureAssociationRole(org.opengis.feature.FeatureAssociationRole)

Example 5 with AttributeTypeBuilder

use of org.apache.sis.feature.builder.AttributeTypeBuilder in project geotoolkit by Geomatys.

the class DataBaseModel method reverseSimpleFeatureTypes.

/**
 * Rebuild simple feature types for each table.
 */
private void reverseSimpleFeatureTypes(final Connection cx) {
    final SQLDialect dialect = store.getDialect();
    for (final SchemaMetaModel schema : schemas.values()) {
        for (final TableMetaModel table : schema.tables.values()) {
            final String tableName = table.name;
            // fill the namespace--------------------------------------------
            final FeatureTypeBuilder ftb = new FeatureTypeBuilder(table.tableType.build());
            final String featureName = ftb.getName().tip().toString();
            ftb.setName(featureName);
            final List<PropertyTypeBuilder> descs = ftb.properties();
            boolean defaultGeomSet = false;
            for (int i = 0, n = descs.size(); i < n; i++) {
                final AttributeTypeBuilder atb = (AttributeTypeBuilder) descs.get(i);
                final String name = atb.getName().tip().toString();
                atb.setName(ensureGMLNS(name));
                // Set the CRS if it's a geometry
                final Class binding = atb.getValueClass();
                if (Geometry.class.isAssignableFrom(binding)) {
                    // look up the type ( should only be one row )
                    final Filter tableFilter = filter(Table.TABLE_SCHEM, schema.name, Table.TABLE_NAME, tableName);
                    final Filter colFilter = FF.equal(FF.property(Column.COLUMN_NAME), FF.literal(name));
                    final Iterator<Map> meta = cacheColumns.filter(FF.and(tableFilter, colFilter));
                    final Map metas = meta.next();
                    // add the attribute as a geometry, try to figure out
                    // its srid first
                    Integer srid = null;
                    CoordinateReferenceSystem crs = null;
                    try {
                        srid = dialect.getGeometrySRID(store.getDatabaseSchema(), tableName, name, metas, cx);
                        if (srid != null)
                            crs = dialect.createCRS(srid, cx);
                    } catch (SQLException e) {
                        String msg = "Error occured determing srid for " + tableName + "." + name;
                        store.getLogger().log(Level.WARNING, msg, e);
                    }
                    atb.setCRS(crs);
                    if (srid != null) {
                        atb.addCharacteristic(JDBCFeatureStore.JDBC_PROPERTY_SRID).setDefaultValue(srid);
                        if (!defaultGeomSet) {
                            atb.addRole(AttributeRole.DEFAULT_GEOMETRY);
                            defaultGeomSet = true;
                        }
                    }
                } else if (GridCoverage.class.isAssignableFrom(binding)) {
                    // look up the type ( should only be one row )
                    final Filter tableFilter = filter(Table.TABLE_SCHEM, schema.name, Table.TABLE_NAME, tableName);
                    final Filter colFilter = FF.equal(FF.property(Column.COLUMN_NAME), FF.literal(name));
                    final Iterator<Map> meta = cacheColumns.filter(FF.and(tableFilter, colFilter));
                    final Map metas = meta.next();
                    // add the attribute as a geometry, try to figure out
                    // its srid first
                    Integer srid = null;
                    CoordinateReferenceSystem crs = null;
                    try {
                        srid = dialect.getGeometrySRID(store.getDatabaseSchema(), tableName, name, metas, cx);
                        if (srid != null)
                            crs = dialect.createCRS(srid, cx);
                    } catch (SQLException e) {
                        String msg = "Error occured determing srid for " + tableName + "." + name;
                        store.getLogger().log(Level.WARNING, msg, e);
                    }
                    atb.setCRS(crs);
                    if (srid != null) {
                        atb.addCharacteristic(JDBCFeatureStore.JDBC_PROPERTY_SRID).setDefaultValue(srid);
                    // not working yet, SIS FeatureTypeBuilder do not reconize Coverage as a geometry type.
                    // if (!defaultGeomSet) {
                    // //create a computed geometry from coverage envelope
                    // PropertyTypeBuilder geomProp = ftb.addProperty(new CoverageGeometryOperation(AttributeConvention.GEOMETRY_PROPERTY, atb.getName().toString()));
                    // try {
                    // ftb.addProperty(FeatureOperations.envelope(
                    // Collections.singletonMap(AbstractOperation.NAME_KEY,AttributeConvention.ENVELOPE_PROPERTY), null, geomProp.build()));
                    // } catch (FactoryException e) {
                    // throw new IllegalStateException(e);
                    // }
                    // defaultGeomSet = true;
                    // }
                    }
                }
            }
            table.simpleFeatureType = ftb;
        }
    }
}
Also used : FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) SQLException(java.sql.SQLException) PropertyTypeBuilder(org.apache.sis.feature.builder.PropertyTypeBuilder) SingleAttributeTypeBuilder(org.geotoolkit.feature.SingleAttributeTypeBuilder) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) Filter(org.opengis.filter.Filter) SQLDialect(org.geotoolkit.db.dialect.SQLDialect) Iterator(java.util.Iterator) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

AttributeTypeBuilder (org.apache.sis.feature.builder.AttributeTypeBuilder)17 FeatureTypeBuilder (org.apache.sis.feature.builder.FeatureTypeBuilder)15 PropertyTypeBuilder (org.apache.sis.feature.builder.PropertyTypeBuilder)10 FeatureType (org.opengis.feature.FeatureType)7 GenericName (org.opengis.util.GenericName)7 SingleAttributeTypeBuilder (org.geotoolkit.feature.SingleAttributeTypeBuilder)6 Geometry (org.locationtech.jts.geom.Geometry)6 AttributeType (org.opengis.feature.AttributeType)6 DataStoreException (org.apache.sis.storage.DataStoreException)5 ArrayList (java.util.ArrayList)4 FeatureAssociationRole (org.opengis.feature.FeatureAssociationRole)4 PropertyType (org.opengis.feature.PropertyType)4 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)4 IOException (java.io.IOException)3 SQLException (java.sql.SQLException)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 QName (javax.xml.namespace.QName)3 MalformedURLException (java.net.MalformedURLException)2 CharacteristicTypeBuilder (org.apache.sis.feature.builder.CharacteristicTypeBuilder)2