package org.openflexo.foundation.ontology.xsd;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import org.openflexo.toolbox.StringUtils;
import com.sun.xml.xsom.XSAnnotation;
import com.sun.xml.xsom.XSAttContainer;
import com.sun.xml.xsom.XSAttGroupDecl;
import com.sun.xml.xsom.XSAttributeDecl;
import com.sun.xml.xsom.XSAttributeUse;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSContentType;
import com.sun.xml.xsom.XSDeclaration;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSFacet;
import com.sun.xml.xsom.XSIdentityConstraint;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSModelGroupDecl;
import com.sun.xml.xsom.XSNotation;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSWildcard;
import com.sun.xml.xsom.XSXPath;
import com.sun.xml.xsom.visitor.XSVisitor;
public class XSDeclarationsFetcher implements XSVisitor {
private static final java.util.logging.Logger logger = org.openflexo.logging.FlexoLogger.getLogger(XSDeclarationsFetcher.class
.getPackage().getName());
private final Set<XSSimpleType> simpleTypes = new HashSet<XSSimpleType>();
private final Set<XSComplexType> complexTypes = new HashSet<XSComplexType>();
private final Set<XSElementDecl> elementDecls = new HashSet<XSElementDecl>();
private final Set<XSAttGroupDecl> attGroupDecls = new HashSet<XSAttGroupDecl>();
private final Set<XSAttributeDecl> attributeDecls = new HashSet<XSAttributeDecl>();
private final Set<XSModelGroupDecl> modelGroupDecls = new HashSet<XSModelGroupDecl>();
private final Map<XSDeclaration, Set<XSAttributeUse>> attributeUses = new HashMap<XSDeclaration, Set<XSAttributeUse>>();
private final Stack<XSDeclaration> path = new Stack<XSDeclaration>();
private final Map<XSDeclaration, XSDeclaration> localOwners = new HashMap<XSDeclaration, XSDeclaration>();
private final Map<String, XSDeclaration> declarations = new HashMap<String, XSDeclaration>();
public void fetch(XSSchemaSet schemaSet) {
for (XSSchema schema : schemaSet.getSchemas()) {
if (StringUtils.isNotEmpty(schema.getTargetNamespace())) {
schema.visit(this);
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("A schema was ignored because of a lack of target namespace.");
}
}
}
logUris();
}
public void fetch(XSSchema schema) {
schema.visit(this);
logUris();
}
public XSDeclaration getDeclaration(String uri) {
return declarations.get(uri);
}
public XSDeclaration getOwner(XSDeclaration declaration) {
if (declaration.isLocal()) {
return localOwners.get(declaration);
}
return null;
}
public String getOwnerUri(String uri) {
XSDeclaration declaration = getDeclaration(uri);
XSDeclaration declOwner = getOwner(declaration);
if (declOwner != null) {
return getUri(declOwner);
}
return null;
}
public String getNamespace(XSDeclaration declaration) {
if (declaration.isLocal()) {
XSDeclaration owner = getOwner(declaration);
return getNamespace(getOwner(declaration)) + "/" + owner.getName();
}
return declaration.getTargetNamespace();
}
public String getUri(XSDeclaration declaration) {
return getNamespace(declaration) + "#" + declaration.getName();
}
public Set<XSAttributeUse> getAttributeUses(XSDeclaration declaration) {
return attributeUses.get(declaration);
}
private boolean register(XSDeclaration decl) {
if (decl.isLocal()) {
localOwners.put(decl, path.lastElement());
}
String uri = getUri(decl);
if (declarations.containsKey(uri)) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Duplicate URI " + uri);
}
return false;
} else {
declarations.put(uri, decl);
return true;
}
}
public void logUris() {
if (logger.isLoggable(Level.INFO)) {
StringBuffer buffer = new StringBuffer("Registered URIs:\n");
for (String uri : declarations.keySet()) {
buffer.append(uri);
buffer.append("\n");
}
logger.info(buffer.toString());
}
}
public Set<XSSimpleType> getSimpleTypes() {
return simpleTypes;
}
public Set<XSComplexType> getComplexTypes() {
return complexTypes;
}
public Set<XSElementDecl> getElementDecls() {
return elementDecls;
}
public Set<XSAttGroupDecl> getAttGroupDecls() {
return attGroupDecls;
}
public Set<XSAttributeDecl> getAttributeDecls() {
return attributeDecls;
}
public Set<XSModelGroupDecl> getModelGroupDecls() {
return modelGroupDecls;
}
@Override
public void schema(XSSchema schema) {
for (XSSimpleType simpleType : schema.getSimpleTypes().values()) {
simpleType(simpleType);
}
for (XSComplexType complexType : schema.getComplexTypes().values()) {
complexType(complexType);
}
for (XSElementDecl elementDecl : schema.getElementDecls().values()) {
elementDecl(elementDecl);
}
for (XSAttGroupDecl attGroupDecl : schema.getAttGroupDecls().values()) {
attGroupDecl(attGroupDecl);
}
for (XSAttributeDecl attributeDecl : schema.getAttributeDecls().values()) {
attributeDecl(attributeDecl);
}
for (XSModelGroupDecl modelGroupDecl : schema.getModelGroupDecls().values()) {
modelGroupDecl(modelGroupDecl);
}
}
@Override
public void simpleType(XSSimpleType simpleType) {
if (simpleType.isGlobal()) {
if (register(simpleType) == false) {
return;
}
simpleTypes.add(simpleType);
}
}
@Override
public void complexType(XSComplexType complexType) {
if (complexType.isGlobal()) {
if (register(complexType) == false) {
return;
}
complexTypes.add(complexType);
path.push(complexType);
}
attContainer(complexType);
complexType.getContentType().visit(this);
if (complexType.isGlobal()) {
path.pop();
}
}
private void attContainer(XSAttContainer attContainer) {
for (XSAttributeUse attributeUse : attContainer.getDeclaredAttributeUses()) {
attributeUse(attributeUse);
}
}
@Override
public void attributeUse(XSAttributeUse attributeUse) {
if (attributeUses.containsKey(path.lastElement()) == false) {
attributeUses.put(path.lastElement(), new HashSet<XSAttributeUse>());
}
attributeUses.get(path.lastElement()).add(attributeUse);
attributeDecl(attributeUse.getDecl());
}
@Override
public void attributeDecl(XSAttributeDecl attributeDecl) {
// Careful, it can be local and not have a name
if (register(attributeDecl) == false) {
return;
}
attributeDecls.add(attributeDecl);
}
@Override
public void attGroupDecl(XSAttGroupDecl attGroupDecl) {
if (attGroupDecl.isGlobal()) {
if (register(attGroupDecl) == false) {
return;
}
attGroupDecls.add(attGroupDecl);
path.push(attGroupDecl);
}
attContainer(attGroupDecl);
if (attGroupDecl.isGlobal()) {
path.pop();
}
}
@Override
public void modelGroupDecl(XSModelGroupDecl modelGroupDecl) {
if (modelGroupDecl.isGlobal()) {
if (register(modelGroupDecl) == false) {
return;
}
modelGroupDecls.add(modelGroupDecl);
path.push(modelGroupDecl);
}
modelGroup(modelGroupDecl.getModelGroup());
if (modelGroupDecl.isGlobal()) {
path.pop();
}
}
@Override
public void modelGroup(XSModelGroup modelGroup) {
for (XSParticle particle : modelGroup.getChildren()) {
particle(particle);
}
}
@Override
public void elementDecl(XSElementDecl elementDecl) {
// TODO Make sure there is no need to test if global first
if (register(elementDecl) == false) {
return;
}
elementDecls.add(elementDecl);
path.push(elementDecl);
if (elementDecl.getType().isLocal()) {
// TODO If it's global it has already been visited, make sure.
elementDecl.getType().visit(this);
}
path.pop();
}
@Override
public void particle(XSParticle particle) {
particle.getTerm().visit(this);
}
@Override
public void empty(XSContentType empty) {
}
@Override
public void annotation(XSAnnotation ann) {
}
@Override
public void facet(XSFacet facet) {
}
@Override
public void notation(XSNotation notation) {
}
@Override
public void wildcard(XSWildcard wc) {
}
@Override
public void identityConstraint(XSIdentityConstraint decl) {
}
@Override
public void xpath(XSXPath xp) {
}
}