/**
* 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<Object, Processor<Object>>{
private StringBuilder buff = new StringBuilder();
private XMLDocument doc;
@Override
protected Processor<Object> 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<XSModelGroup> modelGroupProcessor = new Processor<XSModelGroup>(){
@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<XSElementDeclaration> elemProcessor = new Processor<XSElementDeclaration>(){
@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();
}
}