/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.data.efeature.impl;
import static org.geotools.data.efeature.EFeatureUtils.eGetFeatureValues;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.geotools.data.Transaction;
import org.geotools.data.efeature.EFeature;
import org.geotools.data.efeature.EFeatureInfo;
import org.geotools.data.efeature.EFeatureUtils;
import org.geotools.data.efeature.ESimpleFeature;
import org.geotools.data.efeature.internal.EFeatureDelegate;
import org.geotools.data.efeature.internal.ESimpleFeatureInternal;
import org.geotools.feature.simple.SimpleFeatureImpl;
import org.geotools.filter.identity.FeatureIdImpl;
/**
* @author kengu - 24. juni 2011
*
*/
public class ESimpleFeatureImpl extends SimpleFeatureImpl implements ESimpleFeature {
/**
* Strong cached reference to EFeature {@link EObject data object}
*/
private EObject eObject;
/**
* Strong cached reference to EFeature {@link EFeatureInfo structure}
*/
private EFeatureInfo eStructure;
// -----------------------------------------------------
// Constructors
// -----------------------------------------------------
/**
* {@link ESimpleFeature} delegate constructor
* @param eFeature
* @param transaction
*/
public ESimpleFeatureImpl(ESimpleFeature eFeature, Transaction transaction) {
this(eFeature.eFeature().getStructure(),eFeature.eFeature(),eFeature.getID(),
eGetFeatureValues(eFeature.eFeature().getStructure(),eFeature.eFeature(),transaction));
}
/**
* {@link EFeature} delegate constructor
* @param eFeature
* @param transaction
*/
public ESimpleFeatureImpl(EFeature eFeature, Transaction transaction) {
this(eFeature.getStructure(),eFeature,eFeature.getID(),
eGetFeatureValues(eFeature.getStructure(),eFeature,transaction));
}
/**
* {@link EFeature} compatible {@link EObject} delegate constructor
* @param eStructure
* @param eObject
* @param transaction
*/
public ESimpleFeatureImpl(EFeatureInfo eStructure, EObject eObject, Transaction transaction) {
this(eStructure,eObject,eStructure.toID(eObject),
eGetFeatureValues(eStructure, eObject, transaction));
}
/**
* Trusted constructor
* @param eStructure
* @param eObject
* @param id
* @param values
*/
public ESimpleFeatureImpl(EFeatureInfo eStructure, EObject eObject, String eID, List<Object> values) {
//
// Forward to SimpleFeatureImpl
//
super(values.toArray(), eStructure.getFeatureType(),
new FeatureIdImpl(eID), false, eStructure.eGetAttributeIndex());
//
// Prepare
//
this.eObject = eObject;
this.eStructure = eStructure;
}
// -----------------------------------------------------
// ESimpleFeature implementation
// -----------------------------------------------------
@Override
public EObject eObject() {
//
// Return implementation, not delegate
//
if(eObject instanceof EFeatureDelegate) {
return ((EFeatureDelegate)eObject).eImpl();
}
return eObject;
}
@Override
public EFeature eFeature() {
//
// Return delegate if not a EFeature implementation
//
if(eObject instanceof EFeature) {
return (EFeature)eObject();
}
return new EFeatureDelegate(eStructure, (InternalEObject)eObject, true, null);
}
@Override
public boolean isDetached() {
return eStructure.eHints().eValuesDetached();
}
@Override
public boolean isSingleton() {
return eStructure.eHints().eSingletonFeatures();
}
@Override
public List<Object> read() throws IllegalStateException {
return read(Transaction.AUTO_COMMIT);
}
@Override
public List<Object> read(Transaction transaction) throws IllegalStateException {
//
// Decide if feature values is allowed to be updated from backing store
//
if(!isDetached()) {
throw new IllegalStateException("ESimpleFeature "
+ getType().getTypeName() + " is not detached");
}
//
// Read values from eImpl()
//
List<Object> eValues = EFeatureUtils.eGetFeatureValues(eStructure, eObject, transaction);
//
// Update values
//
values = eValues.toArray();
//
// Finished
//
return eValues;
}
@Override
public List<Object> write() throws IllegalStateException {
return write(Transaction.AUTO_COMMIT);
}
@Override
public List<Object> write(Transaction transaction) throws IllegalStateException {
//
// Decide if feature values is allowed to be updated from backing store
//
if(!isDetached()) {
throw new IllegalStateException("ESimpleFeature "
+ getType().getTypeName() + " is not detached");
}
//
// Get values as list
//
List<Object> eValues = getAttributes();
//
// Write values to eImpl()
//
EFeatureUtils.eSetFeatureValues(eStructure, eObject, eValues, transaction);
//
// Finished
//
return eValues;
}
@Override
public boolean isReleased() {
return eObject == null;
}
@Override
public void release() {
eObject = null;
}
// -----------------------------------------------------
// Object equality implementation
// -----------------------------------------------------
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + getID().hashCode();
hash = 31 * hash + getFeatureType().hashCode();
for(Object it : getAttributes()) {
hash = (null == it ? 0 : it.hashCode());
}
return hash;
}
@Override
public boolean equals(Object obj) {
//
// Sanity checks
//
if (obj == null) {
return false;
}
//
// Same as this?
//
if (obj == this) {
return true;
}
//
// Not same implementation?
//
if (!(obj instanceof ESimpleFeatureInternal)) {
return false;
}
//
// Cast to ESimpleFeatureInternal
//
ESimpleFeatureInternal eFeature = (ESimpleFeatureInternal)obj;
//
// Get this feature ID
//
String eID = getID();
//
// This check shouldn't really be necessary since
// by contract, all features should have an ID.
//
if (getID() == null) {
if (eFeature.getIdentifier() != null) {
return false;
}
}
//
// Is not same feature ID?
//
if (!eID.equals(eFeature.getIdentifier())) {
return false;
}
//
// Is not same feature type.
//
if (!eFeature.getFeatureType().equals(getFeatureType())) {
return false;
}
//
// Get attribute values
//
List<Object> values = getAttributes();
//
// Check all values for inequality
//
for (int i = 0, count = values.size(); i < count; i++) {
//
// Get attribute values
//
Object v1 = values.get(i);
Object v2 = eFeature.getAttribute(i);
//
// Do a guarded check
//
if (v1 == null) {
if (v2 != null) {
return false;
}
} else {
if (!v1.equals(v2)) {
return false;
}
}
}
//
// All values are equal
//
return true;
}
}