001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.reader.xmlschema;
027:
028: import java.util.HashMap;
029: import java.util.Map;
030:
031: import javax.xml.bind.annotation.XmlAnyElement;
032: import javax.xml.namespace.QName;
033:
034: import com.sun.tools.internal.xjc.reader.gbind.Choice;
035: import com.sun.tools.internal.xjc.reader.gbind.Element;
036: import com.sun.tools.internal.xjc.reader.gbind.Expression;
037: import com.sun.tools.internal.xjc.reader.gbind.OneOrMore;
038: import com.sun.tools.internal.xjc.reader.gbind.Sequence;
039: import com.sun.xml.internal.xsom.XSElementDecl;
040: import com.sun.xml.internal.xsom.XSModelGroup;
041: import com.sun.xml.internal.xsom.XSModelGroupDecl;
042: import com.sun.xml.internal.xsom.XSParticle;
043: import com.sun.xml.internal.xsom.XSWildcard;
044: import com.sun.xml.internal.xsom.visitor.XSTermFunction;
045:
046: /**
047: * Visits {@link XSParticle} and creates a corresponding {@link Expression} tree.
048: * @author Kohsuke Kawaguchi
049: */
050: public final class ExpressionBuilder implements
051: XSTermFunction<Expression> {
052:
053: public static Expression createTree(XSParticle p) {
054: return new ExpressionBuilder().particle(p);
055: }
056:
057: private ExpressionBuilder() {
058: }
059:
060: /**
061: * Wildcard instance needs to be consolidated to one,
062: * and this is such instance (if any.)
063: */
064: private GWildcardElement wildcard = null;
065:
066: private final Map<QName, GElementImpl> decls = new HashMap<QName, GElementImpl>();
067:
068: private XSParticle current;
069:
070: /**
071: * We can only have one {@link XmlAnyElement} property,
072: * so all the wildcards need to be treated as one node.
073: */
074: public Expression wildcard(XSWildcard wc) {
075: if (wildcard == null)
076: wildcard = new GWildcardElement();
077: wildcard.particles.add(current);
078: return wildcard;
079: }
080:
081: public Expression modelGroupDecl(XSModelGroupDecl decl) {
082: return modelGroup(decl.getModelGroup());
083: }
084:
085: public Expression modelGroup(XSModelGroup group) {
086: XSModelGroup.Compositor comp = group.getCompositor();
087: if (comp == XSModelGroup.CHOICE) {
088: // empty choice is not epsilon, but empty set,
089: // so this initial value is incorrect. But this
090: // kinda works.
091: // properly handling empty set requires more work.
092: Expression e = Expression.EPSILON;
093: for (XSParticle p : group.getChildren()) {
094: if (e == null)
095: e = particle(p);
096: else
097: e = new Choice(e, particle(p));
098: }
099: return e;
100: } else {
101: Expression e = Expression.EPSILON;
102: for (XSParticle p : group.getChildren()) {
103: if (e == null)
104: e = particle(p);
105: else
106: e = new Sequence(e, particle(p));
107: }
108: return e;
109: }
110: }
111:
112: public Element elementDecl(XSElementDecl decl) {
113: QName n = new QName(decl.getTargetNamespace(), decl.getName());
114:
115: GElementImpl e = decls.get(n);
116: if (e == null)
117: decls.put(n, e = new GElementImpl(n, decl));
118:
119: e.particles.add(current);
120: assert current.getTerm() == decl;
121:
122: return e;
123: }
124:
125: public Expression particle(XSParticle p) {
126: current = p;
127: Expression e = p.getTerm().apply(this );
128:
129: if (p.isRepeated())
130: e = new OneOrMore(e);
131:
132: if (p.getMinOccurs() == 0)
133: e = new Choice(e, Expression.EPSILON);
134:
135: return e;
136: }
137:
138: }
|