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.txw2.model;
027:
028: import com.sun.codemodel.JAnnotationUse;
029: import com.sun.codemodel.JDefinedClass;
030: import com.sun.codemodel.JMethod;
031: import com.sun.codemodel.JMod;
032: import com.sun.codemodel.JType;
033: import com.sun.tools.internal.txw2.NameUtil;
034: import com.sun.tools.internal.txw2.model.prop.ElementProp;
035: import com.sun.tools.internal.txw2.model.prop.LeafElementProp;
036: import com.sun.tools.internal.txw2.model.prop.Prop;
037: import com.sun.xml.internal.txw2.TypedXmlWriter;
038: import com.sun.xml.internal.txw2.annotation.XmlElement;
039: import org.xml.sax.Locator;
040:
041: import javax.xml.namespace.QName;
042: import java.util.HashSet;
043: import java.util.Set;
044:
045: /**
046: * Element declaration.
047: *
048: * @author Kohsuke Kawaguchi
049: */
050: public class Element extends XmlNode {
051: /**
052: * True if this element can be a root element.
053: */
054: public boolean isRoot;
055:
056: private Strategy strategy;
057:
058: public Element(Locator location, QName name, Leaf leaf) {
059: super (location, name, leaf);
060: }
061:
062: /**
063: * Returns true if this element should generate an interface.
064: */
065: private Strategy decideStrategy() {
066: if (isRoot)
067: return new ToInterface();
068:
069: if (hasOneChild() && leaf instanceof Ref
070: && !((Ref) leaf).isInline())
071: return new HasOneRef((Ref) leaf);
072:
073: Set<Leaf> children = collectChildren();
074: for (Leaf l : children) {
075: if (l instanceof XmlNode)
076: // if it has attributes/elements in children
077: // generate an interface
078: return new ToInterface();
079: }
080:
081: // otherwise this element only has data, so just generate methods for them.
082: return new DataOnly();
083: }
084:
085: void declare(NodeSet nset) {
086: strategy = decideStrategy();
087: strategy.declare(nset);
088: }
089:
090: void generate(NodeSet nset) {
091: strategy.generate(nset);
092: }
093:
094: void generate(JDefinedClass clazz, NodeSet nset, Set<Prop> props) {
095: strategy.generate(clazz, nset, props);
096: }
097:
098: private JMethod generateMethod(JDefinedClass clazz, NodeSet nset,
099: JType retT) {
100: String methodName = NameUtil.toMethodName(name.getLocalPart());
101:
102: JMethod m = clazz.method(JMod.PUBLIC, retT, methodName);
103:
104: JAnnotationUse a = m.annotate(XmlElement.class);
105: if (!methodName.equals(name.getLocalPart()))
106: a.param("value", name.getLocalPart());
107: if (nset.defaultNamespace == null
108: || !nset.defaultNamespace
109: .equals(name.getNamespaceURI()))
110: a.param("ns", name.getNamespaceURI());
111:
112: return m;
113: }
114:
115: public String toString() {
116: return "Element " + name;
117: }
118:
119: interface Strategy {
120: void declare(NodeSet nset);
121:
122: void generate(NodeSet nset);
123:
124: void generate(JDefinedClass clazz, NodeSet nset, Set<Prop> props);
125: }
126:
127: /**
128: * Maps to an interface
129: */
130: private class ToInterface implements Strategy {
131: private JDefinedClass clazz;
132:
133: public void declare(NodeSet nset) {
134: String cname;
135: if (alternativeName != null)
136: cname = alternativeName;
137: else
138: cname = name.getLocalPart();
139: clazz = nset.createClass(cname);
140: clazz._implements (TypedXmlWriter.class);
141:
142: clazz.annotate(XmlElement.class).param("value",
143: name.getLocalPart());
144: // TODO: namespace
145: }
146:
147: public void generate(NodeSet nset) {
148: HashSet<Prop> props = new HashSet<Prop>();
149: for (Leaf l : Element.this )
150: l.generate(clazz, nset, props);
151: }
152:
153: public void generate(JDefinedClass outer, NodeSet nset,
154: Set<Prop> props) {
155: if (props.add(new ElementProp(name, clazz)))
156: generateMethod(outer, nset, clazz);
157: }
158: }
159:
160: /**
161: * For things like "element foo {refToAnotherPattern}"
162: */
163: private class HasOneRef implements Strategy {
164: private final Ref ref;
165:
166: public HasOneRef(Ref ref) {
167: this .ref = ref;
168: }
169:
170: public void declare(NodeSet nset) {
171: }
172:
173: public void generate(NodeSet nset) {
174: }
175:
176: public void generate(JDefinedClass clazz, NodeSet nset,
177: Set<Prop> props) {
178: if (props.add(new ElementProp(name, ref.def.clazz)))
179: generateMethod(clazz, nset, ref.def.clazz);
180: }
181: }
182:
183: private class DataOnly implements Strategy {
184: public void declare(NodeSet nset) {
185: }
186:
187: public void generate(NodeSet nset) {
188: }
189:
190: // TODO: code share with Attribute
191: public void generate(JDefinedClass clazz, NodeSet nset,
192: Set<Prop> props) {
193: Set<JType> types = new HashSet<JType>();
194:
195: for (Leaf l : collectChildren()) {
196: if (l instanceof Text) {
197: types.add(((Text) l).getDatatype(nset));
198: }
199: }
200:
201: for (JType t : types) {
202: if (!props.add(new LeafElementProp(name, t)))
203: continue;
204: generateMethod(
205: clazz,
206: nset,
207: nset.opts.chainMethod ? (JType) clazz
208: : nset.codeModel.VOID)
209: .param(t, "value");
210: }
211: }
212: }
213: }
|