/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.cismet.cismap.commons.tools;
import com.vividsolutions.jts.geom.Geometry;
import org.apache.log4j.Logger;
import org.deegree.datatypes.QualifiedName;
import org.deegree.datatypes.Types;
import org.deegree.io.datastore.PropertyPathResolvingException;
import org.deegree.model.feature.AbstractFeatureCollection;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureFactory;
import org.deegree.model.feature.FeatureProperty;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.feature.schema.PropertyType;
import org.deegree.model.feature.schema.SimplePropertyType;
import org.deegree.model.spatialschema.Curve;
import org.deegree.model.spatialschema.GeometryException;
import org.deegree.model.spatialschema.JTSAdapter;
import org.deegree.model.spatialschema.MultiCurve;
import org.deegree.model.spatialschema.MultiPoint;
import org.deegree.model.spatialschema.MultiSurface;
import org.deegree.model.spatialschema.Point;
import org.deegree.model.spatialschema.Polygon;
import org.deegree.model.spatialschema.Surface;
import org.deegree.ogcbase.PropertyPath;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import de.cismet.cismap.commons.features.FeatureServiceFeature;
import de.cismet.cismap.commons.featureservice.FeatureServiceAttribute;
/**
* DOCUMENT ME!
*
* @author therter
* @version $Revision$, $Date$
*/
public class SimpleFeatureCollection extends AbstractFeatureCollection {
//~ Static fields/initializers ---------------------------------------------
private static final Logger LOG = Logger.getLogger(SimpleFeatureCollection.class);
//~ Instance fields --------------------------------------------------------
List<String[]> aliasAttributeList;
private Feature[] features;
private Map<String, FeatureServiceAttribute> attributeMap;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new SimpleFeatureCollection object.
*
* @param id DOCUMENT ME!
* @param features The feature list. This list should not be null or empty
* @param aliasAttributeList DOCUMENT ME!
*/
public SimpleFeatureCollection(final String id,
final de.cismet.cismap.commons.features.FeatureServiceFeature[] features,
final List<String[]> aliasAttributeList) {
this(id, features, aliasAttributeList, null);
}
/**
* Creates a new SimpleFeatureCollection object.
*
* @param id DOCUMENT ME!
* @param features The feature list. This list should not be null or empty
* @param aliasAttributeList DOCUMENT ME!
* @param attributeMap contains all attribute descriptors
*/
public SimpleFeatureCollection(final String id,
final de.cismet.cismap.commons.features.FeatureServiceFeature[] features,
final List<String[]> aliasAttributeList,
final Map<String, FeatureServiceAttribute> attributeMap) {
super(id);
this.features = new Feature[features.length];
this.aliasAttributeList = aliasAttributeList;
this.attributeMap = attributeMap;
int index = 0;
if (aliasAttributeList == null) {
this.aliasAttributeList = generateAliasAttributeList(features);
}
if (features.length > 0) {
final PropertyType[] propTypeArray = getPropertyTypes(features[0]);
for (final FeatureServiceFeature tmp : features) {
this.features[index++] = toDeegreeFeature(tmp, propTypeArray);
}
}
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @param features DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private List<String[]> generateAliasAttributeList(
final de.cismet.cismap.commons.features.FeatureServiceFeature[] features) {
final List<String[]> aliasAttrList = new ArrayList<String[]>();
Map props = null;
if (attributeMap != null) {
props = attributeMap;
} else if ((features[0].getLayerProperties() != null)
&& (features[0].getLayerProperties().getFeatureService() != null)
&& (features[0].getLayerProperties().getFeatureService().getFeatureServiceAttributes() != null)) {
props = features[0].getLayerProperties().getFeatureService().getFeatureServiceAttributes();
} else {
// the feature properties contains always a geometry property. Even, if the feature should not have any
// geometry
props = features[0].getProperties();
}
if ((features != null) && (features.length > 0)) {
for (final Object key : props.keySet()) {
final String[] aliasAttr = new String[2];
aliasAttr[0] = key.toString();
aliasAttr[1] = key.toString();
aliasAttrList.add(aliasAttr);
}
}
return aliasAttrList;
}
@Override
public FeatureProperty getDefaultProperty(final PropertyPath pp) throws PropertyPathResolvingException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setProperty(final FeatureProperty fp, final int i) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void addProperty(final FeatureProperty fp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void removeProperty(final QualifiedName qn) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void replaceProperty(final FeatureProperty fp, final FeatureProperty fp1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Feature cloneDeep() throws CloneNotSupportedException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void clear() {
features = null;
}
@Override
public Feature getFeature(final int i) {
if (features != null) {
return features[i];
}
return null;
}
@Override
public Feature getFeature(final String string) {
if (features != null) {
for (int i = 0; i < features.length; i++) {
if (features[i].getId().equals(string)) {
return features[i];
}
}
}
return null;
}
@Override
public Feature[] toArray() {
return features;
}
@Override
public Iterator<Feature> iterator() {
return Arrays.asList(features).iterator();
}
@Override
public void add(final Feature ftr) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Feature remove(final Feature ftr) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Feature remove(final int i) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int size() {
return features.length;
}
/**
* DOCUMENT ME!
*
* @param feature DOCUMENT ME!
* @param propTypeArray DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Feature toDeegreeFeature(final FeatureServiceFeature feature, final PropertyType[] propTypeArray) {
final Map props = feature.getProperties();
final DefaultFeatureProperty[] propArray = new DefaultFeatureProperty[aliasAttributeList.size()];
int index = 0;
for (final String[] aliasAttr : aliasAttributeList) {
final QualifiedName name = new QualifiedName(aliasAttr[0]);
Object value = props.get(aliasAttr[1]);
if (value instanceof Geometry) {
try {
value = JTSAdapter.wrap((Geometry)value);
} catch (GeometryException ex) {
LOG.error("Cannot convert JTS geometry to deegree geometry.", ex);
}
}
propArray[index++] = new DefaultFeatureProperty(name, value);
}
final FeatureType ft = FeatureFactory.createFeatureType("test", false, propTypeArray);
return FeatureFactory.createFeature(String.valueOf(feature.getId()), ft, propArray);
}
/**
* DOCUMENT ME!
*
* @param feature DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private PropertyType[] getPropertyTypes(final FeatureServiceFeature feature) {
final Map props = feature.getProperties();
final Map<String, FeatureServiceAttribute> featureServiceAttributes;
if (attributeMap != null) {
featureServiceAttributes = attributeMap;
} else {
featureServiceAttributes = feature.getLayerProperties().getFeatureService().getFeatureServiceAttributes();
}
final PropertyType[] propTypeArray = new PropertyType[aliasAttributeList.size()];
int index = 0;
for (final String[] aliasAttr : aliasAttributeList) {
final QualifiedName name = new QualifiedName(aliasAttr[0]);
Object value = props.get(aliasAttr[1]);
if (value instanceof Geometry) {
try {
value = JTSAdapter.wrap((Geometry)value);
} catch (GeometryException ex) {
LOG.error("Cannot convert JTS geometry to deegree geometry.", ex);
}
}
FeatureServiceAttribute attr = featureServiceAttributes.get(aliasAttr[1]);
if (attr == null) {
attr = featureServiceAttributes.get(aliasAttr[1].toUpperCase());
}
propTypeArray[index++] = getPropertyType(name, attr, value);
}
return propTypeArray;
}
/**
* DOCUMENT ME!
*
* @param name DOCUMENT ME!
* @param attr DOCUMENT ME!
* @param value DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private PropertyType getPropertyType(final QualifiedName name,
final FeatureServiceAttribute attr,
final Object value) {
if ((attr != null) && !attr.isGeometry()) {
final Class cl = FeatureTools.getClass(attr);
if (cl.equals(String.class)) {
return new SimplePropertyType(name, Types.VARCHAR, 0, 1);
} else if (cl.equals(Integer.class)) {
return new SimplePropertyType(name, Types.INTEGER, 0, 1);
} else if (cl.equals(Long.class)) {
return new SimplePropertyType(name, Types.BIGINT, 0, 1);
} else if (cl.equals(Double.class)) {
return new SimplePropertyType(name, Types.DOUBLE, 0, 1);
} else if (cl.equals(Date.class)) {
return new SimplePropertyType(name, Types.TIMESTAMP, 0, 1);
} else if (cl.equals(Boolean.class)) {
return new SimplePropertyType(name, Types.BOOLEAN, 0, 1);
} else if (cl.equals(BigDecimal.class)) {
return new SimplePropertyType(name, Types.NUMERIC, 0, 1);
} else {
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Unknown attribute type found. Try to convert it to a deegree type");
}
final int deegreeType = Integer.parseInt(attr.getType());
return new SimplePropertyType(name, deegreeType, 0, 1);
} catch (NumberFormatException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Unknown attribute type cannot be converted to a deegree type.", e);
}
}
}
}
if (value instanceof Integer) {
return new SimplePropertyType(name, Types.INTEGER, 0, 1);
} else if (value instanceof Double) {
return new SimplePropertyType(name, Types.DOUBLE, 0, 1);
} else if (value instanceof String) {
return new SimplePropertyType(name, Types.VARCHAR, 0, 1);
} else if (value instanceof Float) {
return new SimplePropertyType(name, Types.FLOAT, 0, 1);
} else if (value instanceof Polygon) {
return new SimplePropertyType(name, Types.CURVE, 0, 1);
} else if (value instanceof Point) {
return new SimplePropertyType(name, Types.POINT, 0, 1);
} else if (value instanceof MultiPoint) {
return new SimplePropertyType(name, Types.MULTIPOINT, 0, 1);
} else if (value instanceof Long) {
return new SimplePropertyType(name, Types.BIGINT, 0, 1);
} else if (value instanceof Curve) {
return new SimplePropertyType(name, Types.CURVE, 0, 1);
} else if (value instanceof MultiCurve) {
return new SimplePropertyType(name, Types.MULTICURVE, 0, 1);
} else if (value instanceof Surface) {
return new SimplePropertyType(name, Types.SURFACE, 0, 1);
} else if (value instanceof MultiSurface) {
return new SimplePropertyType(name, Types.MULTISURFACE, 0, 1);
} else if (value instanceof Timestamp) {
return new SimplePropertyType(name, Types.TIMESTAMP, 0, 1);
} else {
LOG.error("unbekannter Typ: " + value.getClass().getName());
}
return null;
}
//~ Inner Classes ----------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private class DefaultFeatureProperty implements FeatureProperty {
//~ Instance fields ----------------------------------------------------
private Object value = null;
private QualifiedName name = null;
//~ Constructors -------------------------------------------------------
/**
* constructor for complete initializing the FeatureProperty.
*
* @param name qualified name of the property
* @param value the properties value
*/
DefaultFeatureProperty(final QualifiedName name, final Object value) {
setValue(value);
this.name = name;
}
//~ Methods ------------------------------------------------------------
/**
* returns the qualified name of the property.
*
* @return DOCUMENT ME!
*/
@Override
public QualifiedName getName() {
return name;
}
/**
* returns the value of the property.
*
* @return DOCUMENT ME!
*/
@Override
public Object getValue() {
return value;
}
/**
* returns the value of the property; if the value is null the passed defaultValuewill be returned.
*
* @param defaultValue DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@Override
public Object getValue(final Object defaultValue) {
if (value == null) {
return defaultValue;
}
return value;
}
/**
* sets the value of the property.
*
* @param value DOCUMENT ME!
*/
@Override
public void setValue(final Object value) {
this.value = value;
}
@Override
public String toString() {
String ret = null;
ret = "name = " + name + "\n";
ret += "value = " + value + "\n";
return ret;
}
@Override
public Feature getOwner() {
return null;
}
}
}