All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jlibs.xml.xsd.XSContentModel Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package jlibs.xml.xsd;

import jlibs.core.graph.Path;
import jlibs.core.graph.Processor;
import jlibs.core.graph.WalkerUtil;
import jlibs.core.graph.visitors.ReflectionVisitor;
import jlibs.core.graph.walkers.PreorderWalker;
import jlibs.xml.sax.XMLDocument;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSModelGroup;
import org.apache.xerces.xs.XSParticle;

/**
 * @author Santhosh Kumar T
 */
public class XSContentModel extends ReflectionVisitor>{
    private StringBuilder buff = new StringBuilder();
    private XMLDocument doc;
    
    @Override
    protected Processor getDefault(Object elem){
        return null;
    }

    protected Processor process(XSModelGroup modelGroup){
        return modelGroupProcessor;
    }

    protected Processor process(XSElementDeclaration elem){
        return elemProcessor;
    }

    private void appendCompositor(Path path){
        if(buff.length()>0 && buff.charAt(buff.length()-1)!='('){
            XSModelGroup modelGroup = (XSModelGroup)path.getParentPath(XSModelGroup.class).getElement();
            switch(modelGroup.getCompositor()){
                case XSModelGroup.COMPOSITOR_SEQUENCE:
                    buff.append(" , ");
                    break;
                case XSModelGroup.COMPOSITOR_ALL:
                    buff.append(" ; ");
                    break;
                case XSModelGroup.COMPOSITOR_CHOICE:
                    buff.append(" | ");
                    break;
            }
        }
    }

    private void appendCardinality(Path path){
        path = path.getParentPath(XSParticle.class);
        if(path!=null){
            XSParticle particle = (XSParticle)path.getElement();
            if(particle.getMinOccurs()==1 && particle.getMaxOccurs()==1)
                return;
            if(particle.getMinOccurs()==0 && particle.getMaxOccurs()==1)
                buff.append("?");
            else if(particle.getMinOccurs()==0 && particle.getMaxOccursUnbounded())
                buff.append("*");
            else if(particle.getMinOccurs()==1 && particle.getMaxOccursUnbounded())
                buff.append("+");
            else{
                buff.append("[");
                if(particle.getMaxOccursUnbounded())
                    buff.append(particle.getMinOccurs()).append("+");
                else if(particle.getMinOccurs()==particle.getMaxOccurs())
                    buff.append(particle.getMinOccurs());
                else
                    buff.append(particle.getMinOccurs()).append(",").append(particle.getMaxOccurs());
                buff.append("]");
            }
        }
    }

    private Processor modelGroupProcessor = new Processor(){
        @Override
        public boolean preProcess(XSModelGroup modelGroup, Path path){
            appendCompositor(path);
            buff.append('(');
            return true;
        }

        @Override
        public void postProcess(XSModelGroup modelGroup, Path path){
            buff.append(')');
            appendCardinality(path);
        }
    };

    private Processor elemProcessor = new Processor(){
        @Override
        public boolean preProcess(XSElementDeclaration elem, Path path){
            appendCompositor(path);
            String uri = elem.getNamespace()==null ? "" : elem.getNamespace();
            doc.declarePrefix(uri);
            buff.append(doc.toQName(uri, elem.getName()));
            appendCardinality(path);
            return false;
        }

        @Override
        public void postProcess(XSElementDeclaration elem, Path path){}
    };

    @SuppressWarnings("unchecked")
    public String toString(XSComplexTypeDefinition complexType, XMLDocument doc){
        buff.setLength(0);
        this.doc = doc;
        WalkerUtil.walk(new PreorderWalker(complexType, new XSNavigator()), this);
        this.doc = null;
        return buff.toString();
    }
}