Package org.geotools.data.efeature.internal

Source Code of org.geotools.data.efeature.internal.EFeaturePropertyDelegate

/**
* <copyright>
* </copyright>
*
* $Id$
*/
package org.geotools.data.efeature.internal;

import java.lang.ref.WeakReference;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.geotools.data.Transaction;
import org.geotools.data.efeature.EFeatureAttributeInfo;
import org.geotools.data.efeature.EFeatureProperty;
import org.geotools.data.efeature.EStructureInfo;
import org.opengis.feature.Property;

/**
* An abstract implementation of the model data type {@link EFeatureProperty}.
*
* @author kengu, 22. apr. 2011
*
* @source $URL$
*/
public abstract class EFeaturePropertyDelegate<V, T extends Property, S extends EStructuralFeature>
        implements EFeatureProperty<V, T> {
   
    /**
     * Cached {@link EFeatureInternal} instance containing the {@link Property#getValue() property value}.
     * <p>
     * The {@link #eObject delegate} is stored as a {@link WeakReference weak reference} so it is
     * not prevented from being finalized and garbage collected.
     */
    protected WeakReference<EFeatureInternal> eInternal;
   
    /**
     * Cached {@link Property property data} instance
     */
    protected T eData;

    /**
     * The actual data class.
     */
    protected Class<T> eDataType;

    /**
     * The actual value class.
     */
    protected Class<V> eValueType;
   
    /**
     * Cached {@link EFeatureAttributeInfo}
     */
    protected EFeatureAttributeInfo eStructure;

    /**
     * The id of the {@link EStructuralFeature structural feature}
     * of the {@link #eObject implementation} which contains
     * the {@link #getData() property data}
     */
    protected WeakReference<EStructuralFeature> eStructuralFeature;
   
    /**
     * Cached value when {@link #isDetached() detached}
     */
    protected V eValue;
   
    /**
     * Flag indication that detached value should be updated
     */
    protected Boolean eInitDetached = true;
   
    // -----------------------------------------------------
    //  Constructors
    // -----------------------------------------------------

    /**
     * Default constructor.
     * <p>
     * @param eInternal
     * @param eStructuralFeature
     * @param dataType - {@link #getData() data} type.
     * @param valueType - {@link #getValue() value} type.
     */
    protected EFeaturePropertyDelegate(EFeatureInternal eInternal,
            String eName, Class<T> dataType, Class<V> valueType) {
        //
        // Forward
        //
        super();       
        //
        // Get EFeatureAttribute structure
        //
        this.eStructure = eInternal.eStructure.eGetAttributeInfo(eName, true);
        //
        // EAttribute not found?
        //
        if (this.eStructure == null) {
            throw new IllegalArgumentException("EStructuralFeature '" + eName + "'" + " not found");
        }
        //
        // Do value type sanity check
        //
        EAttribute eAttribute = eStructure.eAttribute();
        Class<?> actualType = eAttribute.getEAttributeType().getInstanceClass();
        if (!valueType.isAssignableFrom(actualType)) {
            //
            // Not correct type
            //
            throw new IllegalArgumentException("Value type '" +
                    valueType.getName() + "'" + " mismatch");
        }
        //
        // Construct delegate
        //           
        this.eDataType = dataType;
        this.eValueType = valueType;
        this.eInternal = new WeakReference<EFeatureInternal>(eInternal);
        this.eStructuralFeature = new WeakReference<EStructuralFeature>(eAttribute);
       
    }

    // -----------------------------------------------------
    //  EFeatureProperty implementation
    // -----------------------------------------------------

    @Override
    public String getName() {
        return getStructuralFeature().getName();
    }
       
    /**
     * Check if EFeaturePropertyDelegate is disposed.
     * <p>
     *
     * @return <code>true</code> if EFeaturePropertyDelegate is disposed.
     */
    public final boolean isDisposed() {
        return eInternal.get() == null
            || eStructuralFeature.get() == null;
    }

    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     */
    @Override
    public final T getData() {
        if (isDisposed()) {
            throw new NullPointerException("Data can not be set to null");
        }

        if (eData == null) {
            eData = create();
        }
        return eData;
    }

    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     */
    @Override
    public final void setData(T newData) {
        // Sanity checks
        //
        if (newData == null) {
            throw new NullPointerException("Data can not be set to null");
        } else if (isDisposed()) {
            throw new NullPointerException("EFeaturePropertyDelegate is disposed");
        }

        // Validate data and return new value
        //
        V newValue = validate(newData);

        //
        // Set new value
        //
        eObject().eSet(eStructuralFeature.get(), newValue);
    }

    @Override
    public final Class<T> getDataType() {
        return eDataType;
    }

    @Override
    public final Class<V> getValueType() {
        return eValueType;
    }
   
    @Override
    public boolean isDetached() {
        return eInternal().eHints.eValuesDetached();
    }

    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     */
    @Override
    public final V getValue() {
        //
        // Detached?
        //
        if(isDetached()) {
            //
            // Initialize detached value?
            //
            if(eInitDetached) {
                return read();
            }
            //
            // Finished
            //   
            return eValue;
           
        } else {
            //
            // Release value
            //
            eValue = null;
            //
            // Set trigger for detached initialization
            //
            eInitDetached = true;
            //
            // Value is attached, read it from structure
            //
            return eValueType.cast(eObject().eGet(eStructuralFeature()));
        }
    }

    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     * @throws NullPointerException If new value is <code>null</code>.
     */
    @Override
    public final void setValue(V newValue) {
        if (newValue == null && !getData().isNillable()) {
            throw new NullPointerException("Value can not be set to null");
        }
        V value = eValueType.cast(newValue);
        if(isDetached()) {
            eValue = newValue;
        } else {
            eObject().eSet(eStructuralFeature(), value);
        }
    }
   
    @Override
    public V read() throws IllegalStateException {
        return read(eInternal().eTx);
    }

    @Override
    public V read(Transaction transaction) throws IllegalStateException {
        //
        // Check if detached
        //
        if(isDetached()) {
            //
            // TODO Implement read lock check
            //
            //
            // Read value from object only when detached
            //
            eValue = eValueType.cast(eObject().eGet(eStructuralFeature()));
            //
            // Flag that detached initialization is completed
            //
            eInitDetached = false;
        }
        //
        // Finished
        //
        return getValue();
    }

    @Override
    public V write() throws IllegalStateException {
        return write(eInternal().eTx);
    }

    @Override
    public V write(Transaction transaction) throws IllegalStateException {           
        //
        // Decide if value is allowed to be updated from backing store
        //
        if(!isDetached()) {
            throw new IllegalStateException("EFeatureProperty "
                    + getName() + " is not detached");
        }
        //
        // TODO Implement write lock check
        //
        eObject().eSet(eStructuralFeature(), eValue);
        //
        // Finished
        //
        return eValue;
    }

    /**
     * @throws IllegalStateException
     *  If {@link EFeatureInternal internal implementation}
     *  is {@link #isDisposed() disposed}.
     */
    @Override
    public final EObject eObject() {       
        return eInternal().eImpl();
    }

    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     */
    @Override
    public final EStructuralFeature getStructuralFeature() {
        return eStructuralFeature();
    }

    @Override
    public EStructureInfo<?> getStructure() {
        return eStructure;
    }

    @Override
    public String toString() {
        StringBuffer result = new StringBuffer(super.toString());
        result.append(" (valueType: ");
        result.append(eValueType);
        result.append(", dataType: ");
        result.append(eDataType);
        result.append(')');
        return result.toString();
    }
   
    // -----------------------------------------------------
    //  EFeaturePropertyDelegate methods
    // -----------------------------------------------------
       
    /**
     * @throws IllegalStateException
     *  If {@link EFeatureInternal internal implementation}
     *  is {@link #isDisposed() disposed}.
     */
    public final EFeatureInternal eInternal() {
        if (isDisposed()) {
            throw new IllegalStateException("EFeatureInternal instance is disposed");
        }
        return eInternal.get();
    }
       
    // -----------------------------------------------------
    //  Abstract EFeaturePropertyDelegate methods
    // -----------------------------------------------------

    /**
     * Create new {@link Property property} instance.
     */
    protected abstract T create();

    /**
     * Validate {@link Property property data} instance.
     *
     * @throws IllegalArgumentException If data is not valid.
     * @return property value casted to {@link #getValueType() value type} if valid.
     */
    protected abstract V validate(T data) throws IllegalArgumentException;

    /**
     * Validate {@link Property#getValue() property value}.
     *
     * @throws IllegalArgumentException If value is not valid.
     * @return property value casted to {@link #getValueType() value type} if valid.
     */
    protected abstract V validate(Object value) throws IllegalArgumentException;

    // -----------------------------------------------------
    //  EFeaturePropertyDelegate helper methods
    // -----------------------------------------------------

    protected final void eSetInitDetachedValues() {
        eInitDetached=true;
    }
   
    /**
     * @throws IllegalStateException If delegate is {@link #isDisposed() disposed}.
     */
    protected final EStructuralFeature eStructuralFeature() {
        if (isDisposed()) {
            throw new IllegalStateException("EFeaturePropertyDelegate is disposed");
        }
        return eStructuralFeature.get();
    }
   

} // EFeaturePropertyDelegate
TOP

Related Classes of org.geotools.data.efeature.internal.EFeaturePropertyDelegate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.