Package org.geotools.xml.impl

Source Code of org.geotools.xml.impl.BindingWalker$Visitor

/*
*    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.XSDFeature;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.picocontainer.MutablePicoContainer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import javax.xml.namespace.QName;

import org.geotools.util.SoftValueHashMap;
import org.geotools.xml.Binding;
import org.geotools.xml.Schemas;
import org.geotools.xs.XS;


/**
*
*
* @source $URL$
*/
public class BindingWalker implements TypeWalker.Visitor {
    BindingLoader loader;
   
    SoftValueHashMap /*<XSDFeature,BindingExecutionChain>*/ chains;
    TypeWalker typeWalker;
    MutablePicoContainer context;
    ArrayList bindings;
    XSDFeature component;
    XSDTypeDefinition container;

    public BindingWalker(BindingLoader factory) {
        this.loader = factory;

        chains = new SoftValueHashMap(100);
        typeWalker = new TypeWalker();
    }
   
    public Binding getAnyTypeBinding() {
        return loader.loadBinding(XS.ANYTYPE, context);
    }

    public boolean visit(XSDTypeDefinition type) {
        //look up the associated binding object for this type
        QName bindingName = null;

        if (type.getName() != null) {
            bindingName = new QName(type.getTargetNamespace(), type.getName());
        } else {
            //anonymous type, does it belong to a global element
            for (Iterator e = type.getSchema().getElementDeclarations().iterator(); e.hasNext();) {
                XSDElementDeclaration element = (XSDElementDeclaration) e.next();

                if (type.equals(element.getAnonymousTypeDefinition())) {
                    //TODO: this naming convention for anonymous types could conflict with
                    // other types in the schema
                    bindingName = new QName(type.getTargetNamespace(), "_" + element.getName());

                    break;
                }
            }

            if (bindingName == null) {
                //do we have a containing type?
                if (container != null) {
                    XSDNamedComponent base = container;
                   
                    //the container itself could be an anonymous type, check for
                    // a named containing element
                    if ( container.getName() == null ) {
                        if ( container.getContainer() instanceof XSDElementDeclaration ) {
                            XSDElementDeclaration e = (XSDElementDeclaration) container.getContainer();
                           
                            //only do this if the containing element is global
                            if ( e.isGlobal() ) {
                                base = e;
                            }
                        }
                    }
                   
                    //get the anonymous element, and look it up in the container type
                    if (type.getContainer() instanceof XSDElementDeclaration) {
                        XSDElementDeclaration anonymous = (XSDElementDeclaration) type.getContainer();
                        XSDParticle particle = Schemas.getChildElementParticle(container,
                                anonymous.getName(), true);

                        if (particle != null) {
                            bindingName = new QName(base.getTargetNamespace(),
                                    base.getName() + "_" + anonymous.getName());
                        }
                    }
                }
            }

            if ((bindingName == null) || (loader.getBinding(bindingName) == null)) {
                //special case check, look for an anonymous complex type
                // with simple content
                if (type instanceof XSDComplexTypeDefinition
                        && type.getBaseType() instanceof XSDSimpleTypeDefinition) {
                    //we assign the default complex binding instread of
                    // delegating to parent, because if we dont, any attributes
                    // defined by the type will not be parsed because simple
                    // types cannot have attributes.
                    //TODO: put this somewhere else, perahps in teh factories
                    // that create the bindings
                    bindingName = XS.ANYTYPE;
                }
            }
        }

        //load the binding into the current context
        Binding binding = loader.loadBinding(bindingName, context);

        if (binding != null) {
            //add the binding
            bindings.add(binding);

            //check execution mode, if override break out
            if (binding.getExecutionMode() == Binding.OVERRIDE) {
                return false;
            }
        }

        return true;
    }

    public void walk(XSDFeature component, Visitor visitor, XSDTypeDefinition container,
        MutablePicoContainer context) {
        BindingExecutionChain chain = (BindingExecutionChain) chains.get(component);

        if (chain == null) {
            this.container = container;
            this.component = component;
            this.context = context;
            this.bindings = new ArrayList();

            //first walk the type hierarchy to get the binding objects
            typeWalker.walk(component.getType(), this);

            //also look up a binding to teh instance itself, if found it will go
            // at the bottom of the binding hierarchy
            if (component.getName() != null) {
                QName qName = new QName(component.getTargetNamespace(), component.getName());
                Binding binding = loader.loadBinding(qName, context);

                if (binding != null) {
                    //check for override
                    if (binding.getExecutionMode() == Binding.OVERRIDE) {
                        //override, clear the binding list
                        bindings.clear();
                        bindings.add(binding);
                    } else {
                        //not override, add as first
                        bindings.add(0, binding);
                    }
                }
            }

            chain = new BindingExecutionChain(bindings);
            chains.put(component, chain);
        }

        chain.execute(visitor);
    }

    public void walk(XSDFeature component, Visitor visitor, MutablePicoContainer context) {
        walk(component, visitor, null, context);
    }

    public static interface Visitor {
        void visit(Binding binding);
    }

    public static class BindingExecutionChain {
        List bindings;

        public BindingExecutionChain(List bindings) {
            this.bindings = bindings;
        }

        public void execute(Visitor visitor) {
            //simulated call stack
            Stack stack = new Stack();

            //visit from bottom to top
            for (int i = 0; i < bindings.size(); i++) {
                Binding binding = (Binding) bindings.get(i);

                if (binding.getExecutionMode() == Binding.AFTER) {
                    //put on stack to execute after parent
                    stack.push(binding);

                    continue;
                }

                //execute the strategy
                visitor.visit(binding);
            }

            //unwind the call stack
            while (!stack.isEmpty()) {
                Binding binding = (Binding) stack.pop();

                visitor.visit(binding);
            }
        }
    }
}
TOP

Related Classes of org.geotools.xml.impl.BindingWalker$Visitor

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.