package org.geotools.data.efeature;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.ecore.EAttribute;
import org.geotools.feature.type.AttributeTypeImpl;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.feature.type.GeometryType;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.util.InternationalString;
import com.vividsolutions.jts.geom.Geometry;
/**
* This class defines a {@link EFeature} {@link Geometry geometry} {@link EAttribute attribute}.
*
* @author kengu
*
*/
public class EFeatureGeometryInfo extends EFeatureAttributeInfo {
protected String srid;
protected String geometryClassName;
protected boolean isDefaultGeometry;
protected CoordinateReferenceSystem crs;
private GeometryDescriptorDelegate descriptor;
// -----------------------------------------------------
// Constructors
// -----------------------------------------------------
/**
* Default constructor
*/
protected EFeatureGeometryInfo() {
super();
}
/**
* Structure copy constructor.
* <p>
* This method copies the structure into given context.
* </p>
* <b>NOTE</b>: This method only adds a one-way reference from
* copied instance to given {@link EFeatureContext context}.
* No reference is added from the context to this attribute.
* </p>
* @param eGeometryInfo - copy from this {@link EFeatureGeometryInfo} instance
* @param eFeatureInfo - copy into this structure
*/
protected EFeatureGeometryInfo(EFeatureGeometryInfo eGeometryInfo, EFeatureInfo eFeatureInfo) {
//
// Forward to EFeatureAttributeInfo
//
super(eGeometryInfo, eFeatureInfo);
//
// Set geometry members
//
this.crs = eGeometryInfo.crs;
this.srid = eGeometryInfo.srid;
this.geometryClassName = eGeometryInfo.geometryClassName;
this.isDefaultGeometry = eGeometryInfo.isDefaultGeometry;
}
// -----------------------------------------------------
// EFeatureGeometryInfo methods
// -----------------------------------------------------
public String getSRID() {
return srid;
}
public boolean isDefaultGeometry() {
return isDefaultGeometry;
}
/**
* Get name of class extending {@link Geometry}.
*
* @return a {@link Geometry} name.
*/
public String getGeometryClassName() {
return geometryClassName;
}
@Override
public GeometryDescriptor getDescriptor() {
if (isAvailable() && descriptor == null) {
descriptor = new GeometryDescriptorDelegate();
}
return descriptor;
}
@Override
public EFeatureStatus validate(boolean isID, EAttribute eAttribute) {
//
// Initialize
//
EFeatureStatus s;
//
// Invalidate structure
//
doInvalidate(false);
// Forward to super class
//
if ((s = super.validate(isID, eAttribute)).isSuccess()) {
// 1) Verify geometry type
//
String eType = eAttribute.getEType().getInstanceClassName();
if (this.geometryClassName != eType) {
return failure(this, eName(), "Geometry type mismatch: Found + " + eType + ", expected "
+ this.geometryClassName);
}
// Confirm that structure is valid
//
return structureIsValid(eName());
}
// Invalidate structure again.
//
doInvalidate(false);
// Is invalid
//
return s;
}
//-----------------------------------------------------
// Methods for staying in-sync with EFeatureInfo parent
// -----------------------------------------------------
protected void setSRID(String srid, CoordinateReferenceSystem crs) {
this.crs = crs;
this.srid = srid;
}
protected void setIsDefaultGeometry(boolean isDefault) {
this.isDefaultGeometry = isDefault;
}
// -----------------------------------------------------
// EStructureInfo implementation
// -----------------------------------------------------
@Override
protected void doDispose() {
super.doDispose();
descriptor = null;
crs = null;
}
// -----------------------------------------------------
// GeometryDescriptor implementation
// -----------------------------------------------------
protected class GeometryDescriptorDelegate extends AttributeDescriptorDelegate implements
GeometryDescriptor {
private GeometryType type;
@Override
public GeometryType getType() {
if (isAvailable() && type == null) {
//
// Get value instance class
//
final Class<?> cls = eAttribute().getEAttributeType().getInstanceClass();
//
// Create anonymous attribute type implementation
//
type = new GeometryTypeDelegate(getName(), cls, eIsID, false,
Collections.<Filter> emptyList(), null, null);
}
return type;
}
@Override
public CoordinateReferenceSystem getCoordinateReferenceSystem() {
return isAvailable() ? getType().getCoordinateReferenceSystem() : null;
}
}
protected class GeometryTypeDelegate extends AttributeTypeImpl implements GeometryType {
private final Class<?> binding;
public GeometryTypeDelegate(Name name, Class<?> binding, boolean identified,
boolean isAbstract, List<Filter> restrictions, AttributeType superType,
InternationalString description) {
// Forward
//
super(name, binding, identified, isAbstract, restrictions, superType, description);
// Enable value parsing
//
this.binding = binding;
}
@Override
public CoordinateReferenceSystem getCoordinateReferenceSystem() {
return crs;
}
@Override
public Object parse(Object value) throws IllegalArgumentException {
return DataBuilder.parse(binding, value);
}
}
// -------------------------------------------------------
// Helper methods
// -------------------------------------------------------
/**
* @param eFeatureInfo
* @param eIsID
* @param isDefault
* @param srid
* @param crs
* @param eAttribute
*/
protected static EFeatureGeometryInfo create(
EFeatureInfo eFeatureInfo,
boolean isDefault, String srid,
CoordinateReferenceSystem crs, EAttribute eAttribute) {
//
// Create new instance
//
EFeatureGeometryInfo eInfo = new EFeatureGeometryInfo();
//
// Set construction hints
//
eInfo.eHints = eFeatureInfo.eHints;
//
// Set context
//
eInfo.eFactory = eFeatureInfo.eFactory;
eInfo.eContext = eFeatureInfo.eContext;
eInfo.eContextID = eFeatureInfo.eContextID;
//
// Set context path
//
eInfo.eNsURI = eFeatureInfo.eNsURI;
eInfo.eFolderName = eFeatureInfo.eFolderName;
eInfo.eFeatureName = eFeatureInfo.eName();
//
// Set other attribute members
//
eInfo.eIsID = false;
eInfo.eName = eAttribute.getName();
eInfo.eAttribute = new WeakReference<EAttribute>(eAttribute);
//
// Set geometry members
//
eInfo.crs = crs;
eInfo.srid = srid;
eInfo.isDefaultGeometry = isDefault;
eInfo.geometryClassName = eAttribute.getEAttributeType().getInstanceClassName();
//
// Finished
//
return eInfo;
}
}