Package org.geotools.xml.impl

Source Code of org.geotools.xml.impl.ParseExecutor

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2008, 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.xml.impl;

import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDEnumerationFacet;
import org.eclipse.xsd.XSDFacet;
import org.eclipse.xsd.XSDFactory;
import org.eclipse.xsd.XSDLengthFacet;
import org.eclipse.xsd.XSDMaxLengthFacet;
import org.eclipse.xsd.XSDMinLengthFacet;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.XSDVariety;
import org.eclipse.xsd.XSDWhiteSpace;
import org.eclipse.xsd.XSDWhiteSpaceFacet;
import org.picocontainer.MutablePicoContainer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.QName;

import org.geotools.xml.AttributeInstance;
import org.geotools.xml.Binding;
import org.geotools.xml.ComplexBinding;
import org.geotools.xml.ElementInstance;
import org.geotools.xml.InstanceComponent;
import org.geotools.xml.Node;
import org.geotools.xml.Schemas;
import org.geotools.xml.SimpleBinding;
import org.geotools.xml.impl.BindingWalker.Visitor;
import org.geotools.xs.facets.Whitespace;


/**
*
*
* @source $URL$
*/
public class ParseExecutor implements Visitor {
    private InstanceComponent instance;
    private Node node;
    private MutablePicoContainer context;
    private ParserHandler parser;

    /**
     * initial binding value
     */
    private Object value;

    /**
     * final parsed result
     */
    private Object result;

    public ParseExecutor(InstanceComponent instance, Node node, MutablePicoContainer context,
        ParserHandler parser) {
        this.instance = instance;
        this.node = node;
        this.context = context;
        this.parser = parser;
    }

    public void visit(Binding binding) {
        //TODO: the check for InstanceBinding is a temporary measure to allow
        // for bindings that are not registered by class, but by instance.
        // in the long term we intend to ditch pico container b/c our inection
        // needs are quite trivial and can be handled by some simple reflection
        if ( !( binding instanceof InstanceBinding ) ) {
            //reload out of context, we do this so that the binding can pick up any new dependencies
            // providedb by this particular context
            Class bindingClass = binding.getClass();
            QName bindingTarget = binding.getTarget();
           
            binding = (Binding) context.getComponentInstanceOfType(binding.getClass());
            if (binding == null) {
               
                binding = parser.getBindingLoader().loadBinding(bindingTarget, context);
                if ( binding == null ) {
                    binding = parser.getBindingLoader().loadBinding(bindingTarget,bindingClass,context);
                }
                if ( binding.getClass() != bindingClass ) {
                    throw new IllegalStateException( "Reloaded binding resulted in different type");
                }
            }   
        }
       

        //execute the binding
        try {
            if (result == null) {
                //no result has been produced yet, should we pass the facet
                // parsed text in? only for simple types or complex types with
                // mixed content
                XSDTypeDefinition type = null;

                if (Schemas.nameMatches(instance.getDeclaration(), binding.getTarget())) {
                    //instance binding
                    type = instance.getTypeDefinition();
                } else {
                    //type binding
                    type = Schemas.getBaseTypeDefinition(instance.getTypeDefinition(),
                            binding.getTarget());
                }

                if (value == null) {
                    //have not preprocessed raw string yet
                    //value = parseFacets( instance );
                    value = preParse(instance);

                    //if the type is simple or complex and mixed, use the
                    // text as is, other wise trim it, turning to null if the
                    // result is empty
                    if ((type != null)
                            && (type instanceof XSDSimpleTypeDefinition
                            || ((XSDComplexTypeDefinition) type).isMixed())) {
                        result = value;
                    } else if ((value != null) && value instanceof String) {
                        value = ((String) value).trim();

                        if ("".equals(value)) {
                            result = null;
                        } else {
                            result = value;
                        }
                    }
                    else {
                        result = value;
                    }
                }
            }

            if (binding instanceof SimpleBinding) {
                result = ((SimpleBinding) binding).parse(instance, result);
            } else {
                result = ((ComplexBinding) binding).parse((ElementInstance) instance, node, result);
            }

            //only pass the value along if it was non-null
            if (result != null) {
                value = result;
            }
        } catch (Throwable t) {
            String msg = "Parsing failed for " + instance.getName() + ": " + t.toString();
            throw new RuntimeException(msg, t);
        }
    }

    public Object getValue() {
        return value;
    }

    /**
     * Pre-parses the instance compontent checking the following:
     * <p>
     *
     * </p>
     * @param instance
     */
    protected Object preParse(InstanceComponent instance) {
        // we only preparse text, so simple types
        XSDSimpleTypeDefinition type = null;

        if (instance.getTypeDefinition() instanceof XSDSimpleTypeDefinition) {
            type = (XSDSimpleTypeDefinition) instance.getTypeDefinition();
        } else {
            XSDComplexTypeDefinition complexType = (XSDComplexTypeDefinition) instance
                .getTypeDefinition();

            if (complexType.getContentType() instanceof XSDSimpleTypeDefinition) {
                type = (XSDSimpleTypeDefinition) complexType.getContentType();
            }
        }

        String text = instance.getText();

        if (type != null) {
            //alright, lets preparse some text
            //first base on variety
            if (type.getVariety() == XSDVariety.LIST_LITERAL) {
                //list, whiteSpace is fixed to "COLLAPSE
                text = Whitespace.COLLAPSE.preparse(text);

                //lists are seperated by spaces
                String[] list = text.split(" +");

                //apply the facets
                // 1. length
                // 2. maxLength
                // 3. minLength
                // 4. enumeration
                if (type.getLengthFacet() != null) {
                    XSDLengthFacet length = type.getLengthFacet();

                    if (list.length != length.getValue()) {
                        //validation exception
                    }
                }

                if (type.getMaxLengthFacet() != null) {
                    XSDMaxLengthFacet length = type.getMaxLengthFacet();

                    if (list.length > length.getValue()) {
                        //validation exception
                    }
                }

                if (type.getMinLengthFacet() != null) {
                    XSDMinLengthFacet length = type.getMinLengthFacet();

                    if (list.length < length.getValue()) {
                        //validation exception
                    }
                }

                if (!type.getEnumerationFacets().isEmpty()) {
                    //gather up all teh possible values
                    Set values = new HashSet();

                    for (Iterator e = type.getEnumerationFacets().iterator(); e.hasNext();) {
                        XSDEnumerationFacet enumeration = (XSDEnumerationFacet) e.next();

                        for (Iterator v = enumeration.getValue().iterator(); v.hasNext();) {
                            values.add(v.next());
                        }
                    }

                    for (int i = 0; i < list.length; i++) {
                        if (!values.contains(list[i])) {
                            //validation exception
                        }
                    }
                }

                //now we must parse the items up
                final XSDSimpleTypeDefinition itemType = type.getItemTypeDefinition();
                List parsed = new ArrayList();

                //create a pseudo declaration
                final XSDElementDeclaration element = XSDFactory.eINSTANCE
                    .createXSDElementDeclaration();
                element.setTypeDefinition(itemType);

                if (instance.getName() != null) {
                    element.setName(instance.getName());
                }

                if (instance.getNamespace() != null) {
                    element.setTargetNamespace(instance.getNamespace());
                }

                //create a new instance of the specified type
                InstanceComponentImpl theInstance = new InstanceComponentImpl() {
                        public XSDTypeDefinition getTypeDefinition() {
                            return itemType;
                        }

                        public XSDNamedComponent getDeclaration() {
                            return element;
                        }
                        ;
                    };
                   
                for (int i = 0; i < list.length; i++) {
                    theInstance.setText(list[i]);

                    //perform the parse
                    ParseExecutor executor = new ParseExecutor(theInstance, null, context, parser);
                    parser.getBindingWalker().walk(element, executor, context);

                    parsed.add(executor.getValue());
                }

                return parsed;
            } else if (type.getVariety() == XSDVariety.UNION_LITERAL) {
                //union, "valueSpace" and "lexicalSpace" facets are the union of the contained
                // datatypes
                return text;
            } else {
                //atomic

                //walk through the facets and preparse as necessary
                for (Iterator f = type.getFacets().iterator(); f.hasNext();) {
                    XSDFacet facet = (XSDFacet) f.next();

                    //white space
                    if (facet instanceof XSDWhiteSpaceFacet) {
                        XSDWhiteSpaceFacet whitespace = (XSDWhiteSpaceFacet) facet;

                        if (whitespace.getValue() == XSDWhiteSpace.REPLACE_LITERAL) {
                            text = Whitespace.REPLACE.preparse(text);
                        }

                        if (whitespace.getValue() == XSDWhiteSpace.COLLAPSE_LITERAL) {
                            text = Whitespace.COLLAPSE.preparse(text);
                        }

                        if (whitespace.getValue() == XSDWhiteSpace.PRESERVE_LITERAL) {
                            //do nothing
                        }
                    }
                }

                return text;
            }
        } else {
            //type is not simple, or complex with simple content, do a check
            // for mixed
            if (instance.getTypeDefinition() instanceof XSDComplexTypeDefinition
                    && ((XSDComplexTypeDefinition) instance.getTypeDefinition()).isMixed()) {
                //collape the text
                text = Whitespace.COLLAPSE.preparse(text);
            }
        }

        return text;
    }

    protected Object parseFacets(InstanceComponent instance) {
        XSDTypeDefinition type = instance.getTypeDefinition();

        String value = instance.getText();

        while (type != null) {
            if (type instanceof XSDSimpleTypeDefinition) {
                XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition) type;
                List facets = simpleType.getFacets();

                for (Iterator itr = facets.iterator(); itr.hasNext();) {
                    XSDFacet facet = (XSDFacet) itr.next();

                    if ("whiteSpace".equals(facet.getFacetName())) {
                        Whitespace whitespace = Whitespace.valueOf(facet.getLexicalValue());

                        if (whitespace != null) {
                            value = whitespace.preparse(value);
                        }

                        //else TODO: check for validation, throw exception?
                    }

                    //TODO: other facets
                }
            }

            if (type.equals(type.getBaseType())) {
                break;
            }

            type = type.getBaseType();
        }

        return value;
    }
}
TOP

Related Classes of org.geotools.xml.impl.ParseExecutor

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.