use of org.opengis.feature.AttributeType in project geotoolkit by Geomatys.
the class GeoJSONReader method fillFeature.
/**
* Recursively fill a ComplexAttribute with properties map
*
* @param feature
* @param properties
*/
private void fillFeature(Feature feature, Map<String, Object> properties) throws BackingStoreException {
final FeatureType featureType = feature.getType();
for (final PropertyType type : featureType.getProperties(true)) {
final String attName = type.getName().toString();
final Object value = properties.get(attName);
if (value == null) {
continue;
}
if (type instanceof FeatureAssociationRole) {
final FeatureAssociationRole asso = (FeatureAssociationRole) type;
final FeatureType assoType = asso.getValueType();
final Class<?> valueClass = value.getClass();
if (valueClass.isArray()) {
Class<?> base = value.getClass().getComponentType();
if (!Map.class.isAssignableFrom(base)) {
LOGGER.log(Level.WARNING, "Invalid complex property value " + value);
}
final int size = Array.getLength(value);
if (size > 0) {
// list of objects
final List<Feature> subs = new ArrayList<>();
for (int i = 0; i < size; i++) {
Object subValue = Array.get(value, i);
final Feature subComplexAttribute;
if (subValue instanceof Map) {
subComplexAttribute = assoType.newInstance();
fillFeature(subComplexAttribute, (Map) Array.get(value, i));
} else if (subValue instanceof GeoJSONFeature) {
subComplexAttribute = toFeature((GeoJSONFeature) subValue, assoType);
} else {
throw new IllegalArgumentException("Sub value must be a GeoJSONFeature or a map");
}
subs.add(subComplexAttribute);
}
feature.setPropertyValue(attName, subs);
}
} else if (value instanceof Map) {
final Feature subComplexAttribute = assoType.newInstance();
fillFeature(subComplexAttribute, (Map) value);
feature.setPropertyValue(attName, subComplexAttribute);
} else if (value instanceof GeoJSONFeature) {
final Feature subComplexAttribute = toFeature((GeoJSONFeature) value, assoType);
feature.setPropertyValue(attName, subComplexAttribute);
} else if (value instanceof GeoJSONFeatureCollection) {
GeoJSONFeatureCollection collection = (GeoJSONFeatureCollection) value;
final List<Feature> subFeatures = new ArrayList<>();
for (GeoJSONFeature subFeature : collection.getFeatures()) {
subFeatures.add(toFeature(subFeature, assoType));
}
feature.setPropertyValue(attName, subFeatures);
} else {
LOGGER.warning("Unexpected attribute value type:" + value.getClass());
}
} else if (type instanceof AttributeType) {
final Attribute<?> property = (Attribute<?>) feature.getProperty(type.getName().toString());
fillProperty(property, value);
}
}
}
use of org.opengis.feature.AttributeType in project geotoolkit by Geomatys.
the class GeoJSONWriter method writeProperties.
/**
* Write ComplexAttribute.
*
* @param edited
* @param fieldName
* @param writeFieldName
* @throws IOException
* @throws IllegalArgumentException
*/
private void writeProperties(Feature edited, String fieldName, boolean writeFieldName, Set<Feature> alreadyWritten) throws IOException, IllegalArgumentException {
if (writeFieldName) {
writer.writeObjectFieldStart(fieldName);
} else {
writer.writeStartObject();
}
FeatureType type = edited.getType();
PropertyType defGeom = FeatureExt.getDefaultGeometrySafe(type).flatMap(Features::toAttribute).orElse(null);
Collection<? extends PropertyType> descriptors = type.getProperties(true).stream().filter(GeoJSONUtils.IS_NOT_CONVENTION).filter(it -> !Objects.equals(defGeom, it)).collect(Collectors.toList());
for (PropertyType propType : descriptors) {
final String name = propType.getName().tip().toString();
final Object value = edited.getPropertyValue(propType.getName().toString());
if (propType instanceof AttributeType) {
final AttributeType attType = (AttributeType) propType;
if (attType.getMaximumOccurs() > 1) {
writer.writeArrayFieldStart(name);
for (Object v : (Collection) value) {
writeProperty(name, v, false, alreadyWritten);
}
writer.writeEndArray();
} else {
writeProperty(name, value, true, alreadyWritten);
}
} else if (propType instanceof FeatureAssociationRole) {
final FeatureAssociationRole asso = (FeatureAssociationRole) propType;
if (asso.getMaximumOccurs() > 1) {
writer.writeFieldName(name);
writeFeatureCollection((List<Feature>) value, asso.getValueType());
} else {
writeProperty(name, value, true, alreadyWritten);
}
} else if (propType instanceof Operation) {
writeProperty(name, value, true, alreadyWritten);
}
}
writer.writeEndObject();
}
use of org.opengis.feature.AttributeType in project geotoolkit by Geomatys.
the class PortrayalServiceTest method testPropertyPreservation.
@Test
public void testPropertyPreservation() throws Exception {
final Point location = GO2Utilities.JTS_FACTORY.createPoint(new Coordinate(2, 3));
final FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("Donaldville");
builder.addAttribute(Point.class).setName("geometry");
builder.addAttribute(String.class).setName("firstName");
builder.addAttribute(String.class).setName("lastName");
final FeatureType duckType = builder.build();
final Feature duck = duckType.newInstance();
duck.setPropertyValue("firstName", "Donald");
duck.setPropertyValue("lastName", "Duck");
duck.setPropertyValue("geometry", location);
final MapLayer layer = MapBuilder.createLayer(new InMemoryFeatureSet(duckType, Collections.singleton(duck)));
final CanvasDef canvas = new CanvasDef(new Dimension(16, 16), new Envelope2D(CommonCRS.defaultGeographic(), 0, 0, 16, 16));
final MapLayers ctx = MapBuilder.createContext();
ctx.getComponents().add(layer);
final SceneDef scene = new SceneDef(ctx);
scene.getHints().put(GO2Hints.KEY_PRESERVE_PROPERTIES, true);
final List<Presentation> result = DefaultPortrayalService.present(canvas, scene).collect(Collectors.toList());
assertEquals(1, result.size());
final Presentation presentation = result.get(0);
final Feature picked = (Feature) presentation.getCandidate();
assertNotNull(picked);
Map<String, Object> expectedProperties = new HashMap<>();
expectedProperties.put("firstName", "Donald");
expectedProperties.put("lastName", "Duck");
expectedProperties.put("geometry", location);
final Map<String, Object> properties = picked.getType().getProperties(true).stream().filter(p -> p instanceof AttributeType).map(attr -> attr.getName().tip().toString()).collect(Collectors.toMap(Function.identity(), name -> picked.getPropertyValue(name)));
assertEquals(String.format("Returned values do not match.%nExpected: %s%nActual: %s%n", expectedProperties.entrySet().stream().map(entry -> String.format("%s -> %s", entry.getKey(), entry.getValue())).collect(Collectors.joining(", ")), properties.entrySet().stream().map(entry -> String.format("%s -> %s", entry.getKey(), entry.getValue())).collect(Collectors.joining(", "))), expectedProperties, properties);
// By default, don't load un-necessary properties
scene.getHints().remove(GO2Hints.KEY_PRESERVE_PROPERTIES);
final List<Object> geometries = DefaultPortrayalService.present(canvas, scene).map(p -> (Feature) p.getCandidate()).peek(Assert::assertNotNull).peek(f -> assertEquals(1, f.getType().getProperties(true).stream().filter(p -> p instanceof AttributeType).count())).map(f -> f.getPropertyValue("geometry")).collect(Collectors.toList());
assertEquals(1, geometries.size());
assertEquals(geometries.get(0), location);
}
use of org.opengis.feature.AttributeType in project geotoolkit by Geomatys.
the class CategoryStyleBuilder method analyze.
public void analyze(final MapLayer layer) {
Resource resource = layer.getData();
if (!(resource instanceof FeatureSet)) {
throw new IllegalArgumentException("Layer resource must be a FeatureSet");
}
this.layer = layer;
fts.rules().clear();
properties.clear();
if (layer != null) {
FeatureType schema;
try {
schema = ((FeatureSet) resource).getType();
} catch (DataStoreException ex) {
throw new FeatureStoreRuntimeException(ex.getMessage(), ex);
}
for (PropertyType desc : schema.getProperties(true)) {
if (desc instanceof AttributeType) {
Class<?> type = ((AttributeType) desc).getValueClass();
if (!Geometry.class.isAssignableFrom(type)) {
properties.add(ff.property(desc.getName().tip().toString()));
}
}
}
// find the geometry class for template
Class<?> geoClass = null;
try {
PropertyType geo = FeatureExt.getDefaultGeometry(schema);
geoClass = Features.toAttribute(geo).map(AttributeType::getValueClass).orElse(null);
} catch (PropertyNotFoundException ex) {
LOGGER.log(Level.FINE, "No sis:geometry property found", ex);
}
if (geoClass == null) {
return;
}
if (Polygon.class.isAssignableFrom(geoClass) || MultiPolygon.class.isAssignableFrom(geoClass)) {
Stroke stroke = sf.stroke(Color.BLACK, 1);
Fill fill = sf.fill(Color.BLUE);
template = sf.polygonSymbolizer(stroke, fill, null);
expectedType = PolygonSymbolizer.class;
} else if (LineString.class.isAssignableFrom(geoClass) || MultiLineString.class.isAssignableFrom(geoClass)) {
Stroke stroke = sf.stroke(Color.BLUE, 2);
template = sf.lineSymbolizer(stroke, null);
expectedType = LineSymbolizer.class;
} else {
Stroke stroke = sf.stroke(Color.BLACK, 1);
Fill fill = sf.fill(Color.BLUE);
List<GraphicalSymbol> symbols = new ArrayList<>();
symbols.add(sf.mark(StyleConstants.MARK_CIRCLE, fill, stroke));
Graphic gra = sf.graphic(symbols, ff.literal(1), ff.literal(12), ff.literal(0), sf.anchorPoint(), sf.displacement());
template = sf.pointSymbolizer(gra, null);
expectedType = PointSymbolizer.class;
}
// try to rebuild the previous analyze if it was one
List<? extends FeatureTypeStyle> ftss = layer.getStyle().featureTypeStyles();
if (ftss.size() == 1) {
FeatureTypeStyle fts = ftss.get(0);
// defensive copy avoid synchronization
List<? extends Rule> candidateRules = new ArrayList<>(fts.rules());
for (Rule r : candidateRules) {
// defensive copy avoid synchronization
List<? extends Symbolizer> candidateSymbols = new ArrayList<>(r.symbolizers());
if (candidateSymbols.size() != 1)
break;
Symbolizer symbol = candidateSymbols.get(0);
if (expectedType.isInstance(symbol)) {
if (r.isElseFilter()) {
// it looks like it's a valid classification "other" rule
this.fts.rules().add((MutableRule) r);
template = symbol;
other = true;
} else {
Filter f = r.getFilter();
if (f != null && f.getOperatorType() == ComparisonOperatorName.PROPERTY_IS_EQUAL_TO) {
BinaryComparisonOperator equal = (BinaryComparisonOperator) f;
Expression exp1 = equal.getOperand1();
Expression exp2 = equal.getOperand2();
if (exp1 instanceof ValueReference && exp2 instanceof Literal) {
if (properties.contains(exp1)) {
// it looks like it's a valid classification property rule
this.fts.rules().add((MutableRule) r);
template = symbol;
currentProperty = (ValueReference) exp1;
} else {
// property is not in the schema
break;
}
} else if (exp2 instanceof ValueReference && exp1 instanceof Literal) {
if (properties.contains(exp2)) {
// it looks like it's a valid classification property rule
this.fts.rules().add((MutableRule) r);
template = symbol;
currentProperty = (ValueReference) exp2;
} else {
// property is not in the schema
break;
}
} else {
// mismatch analyze structure
break;
}
}
}
} else {
break;
}
}
}
}
}
use of org.opengis.feature.AttributeType in project geotoolkit by Geomatys.
the class AbstractReadingTests method testReaders.
/**
* test different readers.
*/
private void testReaders(final FeatureSet featureSet, final ExpectedResult candidate) throws Exception {
final FeatureType type = featureSet.getType();
final Collection<? extends PropertyType> properties = type.getProperties(true);
try (Stream<Feature> stream = featureSet.features(true)) {
stream.forEach((Feature t) -> {
// do nothing
});
throw new Exception("Asking for a reader without any query whould raise an error.");
} catch (Exception ex) {
// ok
}
// property -------------------------------------------------------------
{
// check only id query
final FeatureQuery query = new FeatureQuery();
query.setProjection(new FeatureQuery.NamedExpression(FF.property(AttributeConvention.IDENTIFIER)));
FeatureSet subset = featureSet.subset(query);
FeatureType limited = subset.getType();
assertNotNull(limited);
assertTrue(limited.getProperties(true).size() == 1);
try (Stream<Feature> stream = subset.features(false)) {
final Iterator<Feature> ite = stream.iterator();
while (ite.hasNext()) {
final Feature f = ite.next();
assertNotNull(FeatureExt.getId(f));
}
}
for (final PropertyType desc : properties) {
if (desc instanceof Operation)
continue;
final FeatureQuery sq = new FeatureQuery();
sq.setProjection(new FeatureQuery.NamedExpression(FF.property(desc.getName().tip().toString())));
subset = featureSet.subset(sq);
limited = subset.getType();
assertNotNull(limited);
assertTrue(limited.getProperties(true).size() == 1);
assertNotNull(limited.getProperty(desc.getName().toString()));
try (Stream<Feature> stream = subset.features(false)) {
final Iterator<Feature> ite = stream.iterator();
while (ite.hasNext()) {
final Feature f = ite.next();
assertNotNull(f.getProperty(desc.getName().toString()));
}
}
}
}
// sort by --------------------------------------------------------------
for (final PropertyType desc : properties) {
if (!(desc instanceof AttributeType)) {
continue;
}
final AttributeType att = (AttributeType) desc;
if (att.getMaximumOccurs() > 1) {
// do not test sort by on multi occurence properties
continue;
}
final Class clazz = att.getValueClass();
if (!Comparable.class.isAssignableFrom(clazz) || Geometry.class.isAssignableFrom(clazz)) {
// can not make a sort by on this attribut.
continue;
}
final FeatureQuery query = new FeatureQuery();
query.setSortBy(FF.sort(FF.property(desc.getName().tip().toString()), SortOrder.ASCENDING));
FeatureSet subset = featureSet.subset(query);
// count should not change with a sort by
assertEquals(candidate.size, FeatureStoreUtilities.getCount(subset, true).intValue());
try (Stream<Feature> stream = subset.features(false)) {
final Iterator<Feature> reader = stream.iterator();
Comparable last = null;
while (reader.hasNext()) {
final Feature f = reader.next();
Object obj = f.getProperty(desc.getName().toString()).getValue();
if (obj instanceof Identifier)
obj = ((Identifier) obj).getCode();
final Comparable current = (Comparable) obj;
if (current != null) {
if (last != null) {
// check we have the correct order.
assertTrue(current.compareTo(last) >= 0);
}
last = current;
} else {
// any restriction about where should be placed the feature with null values ? before ? after ?
}
}
}
query.setSortBy(FF.sort(FF.property(desc.getName().tip().toString()), SortOrder.DESCENDING));
subset = featureSet.subset(query);
// count should not change with a sort by
assertEquals(candidate.size, FeatureStoreUtilities.getCount(subset, true).intValue());
try (Stream<Feature> stream = subset.features(false)) {
final Iterator<Feature> reader = stream.iterator();
Comparable last = null;
while (reader.hasNext()) {
final Feature f = reader.next();
Object obj = f.getProperty(desc.getName().toString()).getValue();
if (obj instanceof Identifier)
obj = ((Identifier) obj).getCode();
final Comparable current = (Comparable) obj;
if (current != null) {
if (last != null) {
// check we have the correct order.
assertTrue(current.compareTo(last) <= 0);
}
last = current;
} else {
// any restriction about where should be placed the feature with null values ? before ? after ?
}
}
}
}
// start ----------------------------------------------------------------
if (candidate.size > 1) {
List<ResourceId> ids = new ArrayList<>();
try (Stream<Feature> stream = featureSet.features(false)) {
final Iterator<Feature> ite = stream.iterator();
while (ite.hasNext()) {
ids.add(FeatureExt.getId(ite.next()));
}
}
// skip the first element
final FeatureQuery query = new FeatureQuery();
query.setOffset(1);
try (Stream<Feature> stream = featureSet.subset(query).features(false)) {
final Iterator<Feature> ite = stream.iterator();
int i = 1;
while (ite.hasNext()) {
assertEquals(FeatureExt.getId(ite.next()), ids.get(i));
i++;
}
}
}
// max ------------------------------------------------------------------
if (candidate.size > 1) {
final FeatureQuery query = new FeatureQuery();
query.setLimit(1);
int i = 0;
try (Stream<Feature> stream = featureSet.subset(query).features(false)) {
final Iterator<Feature> ite = stream.iterator();
while (ite.hasNext()) {
ite.next();
i++;
}
}
assertEquals(1, i);
}
// filter ---------------------------------------------------------------
// filters are tested more deeply in the filter module
// we just make a few tests here for sanity check
// todo should we make more deep tests ?
Set<ResourceId> ids = new HashSet<>();
try (Stream<Feature> stream = featureSet.features(false)) {
final Iterator<Feature> ite = stream.iterator();
// peek only one on two ids
boolean oneOnTwo = true;
while (ite.hasNext()) {
final Feature feature = ite.next();
if (oneOnTwo) {
ids.add(FeatureExt.getId(feature));
}
oneOnTwo = !oneOnTwo;
}
}
Set<ResourceId> remaining = new HashSet<>(ids);
final FeatureQuery query = new FeatureQuery();
final Filter f;
switch(ids.size()) {
case 0:
f = Filter.exclude();
break;
case 1:
f = ids.iterator().next();
break;
default:
f = FF.or(ids);
break;
}
query.setSelection(f);
try (Stream<Feature> stream = featureSet.subset(query).features(false)) {
final Iterator<Feature> ite = stream.iterator();
while (ite.hasNext()) {
remaining.remove(FeatureExt.getId(ite.next()));
}
}
assertTrue(remaining.isEmpty());
}
Aggregations