001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.xml.axi.impl;
043:
044: import java.util.ArrayList;
045: import java.util.List;
046: import org.netbeans.modules.xml.axi.AXIComponent;
047: import org.netbeans.modules.xml.axi.AXIModel;
048: import org.netbeans.modules.xml.axi.AXIType;
049: import org.netbeans.modules.xml.axi.AbstractAttribute;
050: import org.netbeans.modules.xml.axi.Compositor;
051: import org.netbeans.modules.xml.axi.ContentModel;
052: import org.netbeans.modules.xml.axi.Element;
053: import org.netbeans.modules.xml.axi.datatype.Datatype;
054: import org.netbeans.modules.xml.axi.visitor.AXIVisitor;
055: import org.netbeans.modules.xml.schema.model.Form;
056: import org.netbeans.modules.xml.schema.model.SchemaComponent;
057: import org.netbeans.modules.xml.schema.model.SimpleType;
058:
059: /**
060: * Element implementation.
061: * @author Samaresh (Samaresh.Panda@Sun.Com)
062: */
063: public final class ElementImpl extends Element {
064:
065: /**
066: * Creates a new instance of ElementImpl
067: */
068: public ElementImpl(AXIModel model) {
069: super (model);
070: }
071:
072: /**
073: * Creates a new instance of ElementImpl
074: */
075: public ElementImpl(AXIModel model, SchemaComponent schemaComponent) {
076: super (model, schemaComponent);
077: }
078:
079: /**
080: * Returns true if it is a reference, false otherwise.
081: */
082: public boolean isReference() {
083: return false;
084: }
085:
086: /**
087: * Returns the referent if isReference() is true.
088: */
089: public Element getReferent() {
090: return null;
091: }
092:
093: /**
094: * Returns abstract property.
095: */
096: public boolean getAbstract() {
097: return isAbstract;
098: }
099:
100: /**
101: * Sets the abstract property.
102: */
103: public void setAbstract(boolean value) {
104: boolean oldValue = getAbstract();
105: if (oldValue != value) {
106: this .isAbstract = value;
107: firePropertyChangeEvent(PROP_ABSTRACT, oldValue, value);
108: }
109: }
110:
111: /**
112: * Returns the block.
113: */
114: public String getBlock() {
115: return block;
116: }
117:
118: /**
119: * Sets the block property.
120: */
121: public void setBlock(String value) {
122: String oldValue = getBlock();
123: if ((oldValue == null && value == null)
124: || (oldValue != null && oldValue.equals(value))) {
125: return;
126: }
127: this .block = value;
128: firePropertyChangeEvent(PROP_BLOCK, oldValue, value);
129: }
130:
131: /**
132: * Returns the final property.
133: */
134: public String getFinal() {
135: return finalValue;
136: }
137:
138: /**
139: * Sets the final property.
140: */
141: public void setFinal(String value) {
142: String oldValue = getFinal();
143: if ((oldValue == null && value == null)
144: || (oldValue != null && oldValue.equals(value))) {
145: return;
146: }
147: this .finalValue = value;
148: firePropertyChangeEvent(PROP_FINAL, oldValue, value);
149: }
150:
151: /**
152: * Returns the fixed value.
153: */
154: public String getFixed() {
155: return fixedValue;
156: }
157:
158: /**
159: * Sets the fixed value.
160: */
161: public void setFixed(String value) {
162: String oldValue = getFixed();
163: if ((oldValue == null && value == null)
164: || (oldValue != null && oldValue.equals(value))) {
165: return;
166: }
167: this .fixedValue = value;
168: firePropertyChangeEvent(PROP_FIXED, oldValue, value);
169: }
170:
171: /**
172: * Returns the default value.
173: */
174: public String getDefault() {
175: return defaultValue;
176: }
177:
178: /**
179: * Sets the default value.
180: */
181: public void setDefault(String value) {
182: String oldValue = getDefault();
183: if ((oldValue == null && value == null)
184: || (oldValue != null && oldValue.equals(value))) {
185: return;
186: }
187: this .defaultValue = value;
188: firePropertyChangeEvent(PROP_DEFAULT, oldValue, value);
189: }
190:
191: /**
192: * Returns the form.
193: */
194: public Form getForm() {
195: return form;
196: }
197:
198: /**
199: * Sets the form.
200: */
201: public void setForm(Form value) {
202: Form oldValue = getForm();
203: if (oldValue != value) {
204: this .form = value;
205: firePropertyChangeEvent(PROP_FORM, oldValue, value);
206: }
207: }
208:
209: /**
210: * Returns the nillable.
211: */
212: public boolean getNillable() {
213: return isNillable;
214: }
215:
216: /**
217: * Sets the nillable property.
218: */
219: public void setNillable(boolean value) {
220: boolean oldValue = getNillable();
221: if (oldValue != value) {
222: this .isNillable = value;
223: firePropertyChangeEvent(PROP_NILLABLE, oldValue, value);
224: }
225: }
226:
227: /**
228: * Returns the AXIType.
229: */
230: public AXIType getType() {
231: if (axiType != null)
232: return axiType;
233:
234: this .axiType = Util.getAXIType(this , typeSchemaComponent);
235: return axiType;
236: }
237:
238: /**
239: * Sets the AXIType.
240: */
241: public void setType(AXIType newValue) {
242: if ((this == newValue)
243: || (this .isGlobal() && (newValue instanceof Element)))
244: return;
245:
246: if (newValue instanceof Element) {
247: setElementAsType(newValue);
248: return;
249: }
250:
251: AXIType oldValue = getType();
252: if (!Util.canSetType(oldValue, newValue))
253: return;
254:
255: updateChildren(oldValue, newValue);
256: this .axiType = newValue;
257: firePropertyChangeEvent(PROP_TYPE, oldValue, newValue);
258: setTypeSchemaComponent(getSchemaType(newValue));
259: }
260:
261: private void setElementAsType(final AXIType newValue) {
262: if (newValue == this )
263: return;
264: int index = this .getIndex();
265: AXIComponent parent = getParent();
266: Element ref = getModel().getComponentFactory()
267: .createElementReference((Element) newValue);
268: parent.removeChild(this );
269: parent.insertAtIndex(Element.PROP_ELEMENT_REF, ref, index);
270: }
271:
272: /**
273: * Overwrites populateChildren of AXIComponent.
274: *
275: * An AXI element can keep LocalElement, GlobalElement or
276: * ElementReference as its peer. For the local and global,
277: * element, the element type's children becomes this AXI
278: * element's children. For ElementReference, the global element's
279: * type becomes this AXI element's children.
280: */
281: public void populateChildren(List<AXIComponent> children) {
282: if (getPeer() == null) {
283: return;
284: }
285:
286: //populate children from the element's type
287: SchemaComponent type = Util.getSchemaType(
288: (AXIModelImpl) getModel(), getPeer());
289: setTypeSchemaComponent(type);
290:
291: if (type == null || type instanceof SimpleType)
292: return;
293:
294: AXIModelBuilder builder = new AXIModelBuilder(this );
295: builder.populateChildren(type, false, children);
296: }
297:
298: /**
299: * Returns the last value for the element's type.
300: */
301: SchemaComponent getTypeSchemaComponent() {
302: return typeSchemaComponent;
303: }
304:
305: /**
306: * Sets the new value for the element's type.
307: */
308: void setTypeSchemaComponent(SchemaComponent type) {
309: this .typeSchemaComponent = type;
310: }
311:
312: private SchemaComponent getSchemaType(AXIType axiType) {
313: if (axiType instanceof Datatype)
314: return null;
315: if (axiType instanceof ContentModel)
316: return ((ContentModel) axiType).getPeer();
317: if (axiType instanceof AnonymousType)
318: return ((AnonymousType) axiType).getPeer();
319:
320: return null;
321: }
322:
323: /**
324: * OLD VALUE NEW VALUE RESULT
325: * SType LCT return
326: * SType GCT add proxy children
327: * LCT SType remove all and return
328: * LCT GCT remove all and add proxy children
329: * GCT SType remove all and return
330: * GCT LCT not allowed
331: */
332: private void updateChildren(AXIType oldValue, AXIType newValue) {
333: //do not remove children if the old type was SimpleType and
334: //user added children on top of it, that makes the type as anonymous.
335: if (oldValue instanceof Datatype
336: && newValue instanceof AnonymousType) {
337: return;
338: }
339:
340: //remove all children anyway
341: removeAllChildren();
342: if ((newValue == null) || (newValue instanceof Datatype)) {
343: return;
344: }
345:
346: //remove listener from old content model
347: if (oldValue != null && oldValue instanceof ContentModel) {
348: ContentModel cm = (ContentModel) oldValue;
349: cm.removeListener(this );
350: }
351:
352: //add proxy children for the new content model
353: if (newValue instanceof ContentModel)
354: Util.addProxyChildren(this , (ContentModel) newValue, null);
355:
356: if (newValue instanceof AnonymousType) {
357: List<AXIComponent> children = new ArrayList<AXIComponent>();
358: AXIModelBuilder builder = new AXIModelBuilder(this );
359: builder.populateChildren(((AnonymousType) newValue)
360: .getPeer(), false, children);
361: for (AXIComponent child : children) {
362: this .appendChild(child);
363: }
364: }
365: }
366:
367: /**
368: * Represents a local complex type.
369: */
370: public static class AnonymousType implements AXIType {
371: private SchemaComponent schemaComponent;
372:
373: public AnonymousType(SchemaComponent schemaComponent) {
374: this .schemaComponent = schemaComponent;
375: }
376:
377: public String getName() {
378: return null;
379: }
380:
381: public void accept(AXIVisitor visitor) {
382: }
383:
384: public SchemaComponent getPeer() {
385: return schemaComponent;
386: }
387: }
388:
389: /**
390: * Overwrites addCompositor of AXIContainer.
391: */
392: public void addCompositor(Compositor compositor) {
393: if (getType() != null && getType() instanceof ContentModel
394: && getModel() != ((ContentModel) getType()).getModel()) {
395: //no drops allowed when the element's type
396: //belongs to some other model
397: return;
398: }
399:
400: if (getType() instanceof Datatype) {
401: setType(new AnonymousType(null));
402: }
403: super .addCompositor(compositor);
404: }
405:
406: /**
407: * Overwrites addAttribute of AXIContainer.
408: */
409: public void addAttribute(AbstractAttribute attribute) {
410: AXIType type = getType();
411: if (type != null && type instanceof ContentModel) {
412: ((ContentModel) type).addAttribute(attribute);
413: return;
414: }
415:
416: if (type instanceof Datatype) {
417: setType(new AnonymousType(null));
418: }
419:
420: super .addAttribute(attribute);
421: }
422:
423: private AXIType axiType;
424: private SchemaComponent typeSchemaComponent;
425: }
|