Package org.locationtech.udig.project.ui.internal

Source Code of org.locationtech.udig.project.ui.internal.FeatureTypeMatch

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.project.ui.internal;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;

/**
* This class is used to determine whether a FeatureEditor can be used to edit a feature of a given
* SimpleFeatureType.
* <p>
* This class uses the SimpleFeatureType element of the FeatureEditor Extension point to determine
* whether the editor can be used. See the FeatureEditor extension point declaration for more
* information.
* </p>
*
* @author jones
* @since 1.0.0
*/
public class FeatureTypeMatch {

    /**
     * Matches a features attributeType to the featureType declared in the extension.
     *
     * @author jones
     * @since 1.0.0
     */
    protected static class AttributeMatcher {
        String name;
        Class< ? > type;

        /**
         * New instance.
         */
        public AttributeMatcher( IConfigurationElement attr ) {
            name = attr.getAttribute("name"); //$NON-NLS-1$
            try {
                type = Class.forName(attr.getAttribute("type")); //$NON-NLS-1$
            } catch (Exception e) {
                ProjectUIPlugin
                        .log(
                                "Extension declaration incorrect:" + attr.getDeclaringExtension().getUniqueIdentifier(), e); //$NON-NLS-1$
            }
        }

        /**
         * returns true if the attr.getType == type and (name==null or name.equals(attr.getName))
         *
         * @param attr
         * @return
         */
        public AttributeDescriptor match( SimpleFeatureType featureType,
                List<AttributeDescriptor> used ) {
            if (name != null) {
                AttributeDescriptor attr = featureType.getDescriptor(name);
                if (type == null || attr == null)
                    return null;
                if (type != attr.getType().getBinding())
                    return null;
                return attr;
            }
            for( int i = 0; i < featureType.getAttributeCount(); i++ ) {
                if (!used.contains(featureType.getDescriptor(i))) {
                    if (type == featureType.getDescriptor(i).getType().getBinding())
                        return featureType.getDescriptor(i);
                }
            }
            return null;
        }
        @Override
        public String toString() {
            StringBuffer buf = new StringBuffer();
            buf.append("match(");
            if (this.name != null) {
                buf.append(this.name);
            }
            if (this.type != null) {
                buf.append(" ");
                buf.append(type.getSimpleName());
            }
            buf.append(")");
            return buf.toString();
        }
    }
    /** A matcher that matches all FeatureTypes */
    public static final FeatureTypeMatch ALL = new FeatureTypeMatch(){
        public int matches( Object firstElement ) {
            if (firstElement == null)
                return -1;
            return Integer.MAX_VALUE - 1;
        }
    };
    private URI namespace;
    private String typeName;
    private AttributeMatcher[] attributes;

    FeatureTypeMatch() {
        // do nothing
    }

    /**
     * Create a FeatureTypeMatcher Object
     *
     * @param element
     */
    public FeatureTypeMatch( IConfigurationElement element ) {
        if (element.getChildren("typeName").length == 1) { //$NON-NLS-1$
            IConfigurationElement typeName = element.getChildren("typeName")[0]; //$NON-NLS-1$
            this.typeName = typeName.getAttribute("name"); //$NON-NLS-1$
            try {
                this.namespace = new URI(typeName.getAttribute("namespace")); //$NON-NLS-1$
            } catch (Exception e) {
                ProjectUIPlugin.log(Messages.FeatureTypeMatch_BadURI, e);
            }
        } else {
            IConfigurationElement[] attributes = element.getChildren("attribute"); //$NON-NLS-1$
            this.attributes = new AttributeMatcher[attributes.length];

            for( int i = 0; i < attributes.length; i++ ) {
                IConfigurationElement attr = attributes[i];
                this.attributes[i] = new AttributeMatcher(attr);
            }
        }

    }
    /**
     * @param element
     * @return true if matches( element ) is greater the -1
     */
    public boolean isMatch( Object element ) {
        int matches = matches(element);
        return matches > -1;
    }

    public static int PERFECT = 0;
    public static int NO_MATCH = -1;
    /**
     * Returns >-1 if the editor has specified a SimpleFeatureType declaration that matches the
     * SimpleFeature passed in as a parameter. Each inaccuracy increases the count by 1. a 0 is a
     * perfect match, using the featureType name and namespace. 1 would be all the attributeTypes
     * have a name and type and there are no extra attributes in the feature's feature type.
     * <p>
     * The matching is done as follows:
     * <ul>
     * <li>If the object is not a feature false is returned.</li>
     * <li>If namespace is not null then the matching is done by matching the namespace and name of
     * the featureType</li>
     * <li>Otherwise the attributes used to match. Two passes are made through the attributes
     * declared in then extension:
     * <ul>
     * <li>First all attributes that are declared and have names associated are processed. There
     * must be an exact match between the declared attribute and one of the attributeTypes in the
     * feature</li>
     * <li>Second all the attributes without declared names are processed. only the type is used to
     * find a match and each attributeType may be matched only once</li>
     * </ul>
     * </ul>
     *
     * @param element
     * @return 0 for a perfect match,
     */
    public int matches( Object element ) {
      SimpleFeatureType schema = null;
      if (element instanceof SimpleFeature) {
          schema = ((SimpleFeature) element).getFeatureType();
      } else if (element instanceof SimpleFeatureType) {
          schema = (SimpleFeatureType) element;
      } else if(element instanceof IAdaptable) {
        IAdaptable adaptable = (IAdaptable) element;
        if(adaptable.getAdapter(SimpleFeatureType.class) != null) {
          schema = (SimpleFeatureType) adaptable.getAdapter(SimpleFeatureType.class);
        } else if(adaptable.getAdapter(SimpleFeature.class) != null) {
          schema = ((SimpleFeature) adaptable.getAdapter(SimpleFeatureType.class)).getFeatureType();
        }
      }

        if (schema != null) {
            Name featureName = schema.getName();
            if (namespace != null) {

                if (namespace.compareTo(URI.create(featureName.getNamespaceURI())) == 0
                        && typeName.equals(featureName.getLocalPart())) {
                    return PERFECT;
                }
                return NO_MATCH;
            }
            if (attributes.length == 0) {
                return NO_MATCH;
            }
            int accuracy = 0;
            accuracy++;
            List<AttributeDescriptor> matched = new ArrayList<AttributeDescriptor>();
            // 1st pass check all named attributes are accounted for
            for( AttributeMatcher current : attributes ) {
                if (current.name == null) {
                    continue; // skip
                }
                AttributeDescriptor currentMatch = current.match(schema, matched);
                if (currentMatch == null) {
                    return NO_MATCH;
                }
                matched.add(currentMatch);
            }
            // section pass check unnamed attributes ... match default geometry type?
            for( AttributeMatcher current : attributes ) {
                if (current.name != null) {
                    continue;
                }
                accuracy++;

                AttributeDescriptor currentMatch = current.match(schema, matched);
                if (currentMatch == null) {
                    return NO_MATCH;
                }
                matched.add(currentMatch);
            }
            accuracy += schema.getAttributeCount() - matched.size();
            return accuracy;
        }
        return NO_MATCH;
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("FeatureTypeMatch ");
        if (this.namespace != null) {
            buf.append(this.namespace);
        }
        buf.append(this.typeName);
        if (this.attributes != null) {
            for( int i = 0; i < this.attributes.length; i++ ) {
                buf.append(this.attributes[i]);
                if (i < this.attributes.length - 1) {
                    buf.append(",");
                }
            }
        }
        return buf.toString();
    }
}
TOP

Related Classes of org.locationtech.udig.project.ui.internal.FeatureTypeMatch

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.