/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2016, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.db; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.sis.feature.AbstractAssociation; import org.apache.sis.feature.AbstractOperation; import org.apache.sis.feature.DefaultAssociationRole; import org.apache.sis.feature.DefaultAttributeType; import org.apache.sis.feature.FeatureExt; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.parameter.DefaultParameterDescriptorGroup; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.data.FeatureIterator; import org.geotoolkit.data.query.QueryBuilder; import org.geotoolkit.db.reverse.RelationMetaModel; import org.geotoolkit.util.NamesExt; import org.opengis.feature.AttributeType; import org.opengis.feature.Feature; import org.opengis.feature.FeatureAssociationRole; import org.opengis.feature.FeatureType; import org.opengis.feature.IdentifiedType; import org.opengis.feature.InvalidPropertyValueException; import org.opengis.feature.MultiValuedPropertyException; import org.opengis.feature.Property; import org.opengis.metadata.Identifier; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterValueGroup; import org.opengis.util.GenericName; /** * * @author Johann Sorel (Geomatys) */ public class DBRelationOperation extends AbstractOperation { /** * @todo this is a copy of {@code LinkOperation} package private method. */ static ParameterDescriptorGroup parameters(final String name, final int minimumOccurs, final ParameterDescriptor<?>... parameters) { final Map<String,Object> properties = new HashMap<>(4); properties.put(ParameterDescriptorGroup.NAME_KEY, name); properties.put(Identifier.AUTHORITY_KEY, Citations.SIS); return new DefaultParameterDescriptorGroup(properties, minimumOccurs, 1); } private static final ParameterDescriptorGroup EMPTY_PARAMS = parameters("JDBCRelation", 1); private final JDBCFeatureStore store; private final RelationMetaModel relation; private String typeName; private FeatureAssociationRole type; public DBRelationOperation(GenericName name, JDBCFeatureStore store, RelationMetaModel template, String typeName){ super(Collections.singletonMap(DefaultAttributeType.NAME_KEY, name)); this.store = store; this.relation = template; this.typeName = typeName; } public RelationMetaModel getRelation() { return relation; } @Override public ParameterDescriptorGroup getParameters() { return EMPTY_PARAMS; } @Override public IdentifiedType getResult() { if (type==null) { final GenericName name = getName(); FeatureType valueType = null; try{ valueType = store.getDatabaseModel().getFeatureType(typeName); }catch (DataStoreException ex) { return new FeatureTypeBuilder().setName("unset").build(); } if(relation.isImported()){ type = new DefaultAssociationRole(Collections.singletonMap("name", name), valueType, 0, 1); }else{ AttributeType att = (AttributeType) valueType.getProperty(relation.getForeignColumn()); final boolean unique = FeatureExt.getCharacteristicValue(att, JDBCFeatureStore.JDBC_PROPERTY_UNIQUE.getName().toString(), Boolean.FALSE); type = new DefaultAssociationRole(Collections.singletonMap("name", name), valueType, 0, unique ? 1 : Integer.MAX_VALUE); } } return type; } @Override public Property apply(Feature ftr, ParameterValueGroup pvg) { final Object key = ftr.getPropertyValue(relation.getCurrentColumn()); final QueryBuilder qb = new QueryBuilder(); qb.setTypeName(NamesExt.create(store.getDefaultNamespace(), relation.getForeignTable())); qb.setFilter(relation.toFilter(key)); final FeatureCollection res = store.createSession(false).getFeatureCollection(qb.buildQuery()); final Object value; if(type.getMaximumOccurs()==1){ try (FeatureIterator ite = res.iterator()) { if(ite.hasNext()){ value = ite.next(); }else{ value = null; } } }else{ value = res; } return new AbstractAssociation(type) { @Override public Feature getValue() throws MultiValuedPropertyException { if(value==null || value instanceof Feature){ return (Feature) value; } throw new MultiValuedPropertyException(); } @Override public Collection<Feature> getValues() { if(value==null){ return Collections.EMPTY_LIST; } else if(value instanceof Feature){ return Arrays.asList((Feature)value); }else{ return res; } } @Override public void setValue(Feature value) throws InvalidPropertyValueException { throw new UnsupportedOperationException("Not supported."); } }; } }