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-2006 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: package org.netbeans.tax;
042:
043: import java.util.Arrays;
044: import java.util.List;
045: import java.util.LinkedList;
046: import java.util.StringTokenizer;
047:
048: /**
049: * @author Libor Kramolis
050: * @version 0.1
051: */
052: public class TreeAttlistDeclAttributeDef extends TreeNodeDecl.Content
053: implements TreeNamedObjectMap.NamedObject {
054:
055: /** */
056: public static final String PROP_NAME = "name"; // NOI18N
057: /** */
058: public static final String PROP_TYPE = "type"; // NOI18N
059: /** */
060: public static final String PROP_ENUMERATED_TYPE = "enumeratedType"; // NOI18N
061: /** */
062: public static final String PROP_DEFAULT_TYPE = "defaultType"; // NOI18N
063: /** */
064: public static final String PROP_DEFAULT_VALUE = "defaultValue"; // NOI18N
065:
066: /** */
067: public static final short TYPE_CDATA = 0;
068: /** */
069: public static final short TYPE_ID = 1;
070: /** */
071: public static final short TYPE_IDREF = 2;
072: /** */
073: public static final short TYPE_IDREFS = 3;
074: /** */
075: public static final short TYPE_ENTITY = 4;
076: /** */
077: public static final short TYPE_ENTITIES = 5;
078: /** */
079: public static final short TYPE_NMTOKEN = 6;
080: /** */
081: public static final short TYPE_NMTOKENS = 7;
082: /** */
083: public static final short TYPE_ENUMERATED = 8;
084: /** */
085: public static final short TYPE_NOTATION = 9;
086:
087: /** */
088: public static final short DEFAULT_TYPE_NULL = 0;
089: /** */
090: public static final short DEFAULT_TYPE_REQUIRED = 1;
091: /** */
092: public static final short DEFAULT_TYPE_IMPLIED = 2;
093: /** */
094: public static final short DEFAULT_TYPE_FIXED = 3;
095:
096: /** */
097: public static final String[] NAMED_TYPE_LIST = new String[] {
098: "CDATA", // TYPE_CDATA // NOI18N
099: "ID", // TYPE_ID // NOI18N
100: "IDREF", // TYPE_IDREF // NOI18N
101: "IDREFS", // TYPE_IDREFS // NOI18N
102: "ENTITY", // TYPE_ENTITY // NOI18N
103: "ENTITIES", // TYPE_ENTITIES // NOI18N
104: "NMTOKEN", // TYPE_NMTOKEN // NOI18N
105: "NMTOKENS", // TYPE_NMTOKENS // NOI18N
106: null, // TYPE_ENUMERATED
107: "NOTATION" // TYPE_NOTATION // NOI18N
108: };
109:
110: /** */
111: public static final String[] NAMED_DEFAULT_TYPE_LIST = new String[] {
112: null, // DEFAULT_TYPE_NULL
113: "#REQUIRED", // DEFAULT_TYPE_REQUIRED // NOI18N
114: "#IMPLIED", // DEFAULT_TYPE_IMPLIED // NOI18N
115: "#FIXED" // DEFAULT_TYPE_FIXED // NOI18N
116: };
117:
118: /** */
119: private String name;
120:
121: /** */
122: private short type;
123:
124: /** */
125: private String[] enumeratedType;
126:
127: /** */
128: private short defaultType;
129:
130: /** */
131: private String defaultValue;
132:
133: /** */
134: private TreeNamedObjectMap.KeyListener mapKeyListener;
135:
136: //
137: // init
138: //
139:
140: /** Creates new TreeAttlistDeclAttributeDef. */
141: public TreeAttlistDeclAttributeDef(String name, short type,
142: String[] enumeratedType, short defaultType,
143: String defaultValue) throws InvalidArgumentException {
144: super ();
145:
146: checkName(name);
147: checkType(type, enumeratedType);
148: checkDefaultType(defaultType, defaultValue);
149: this .name = name;
150: this .type = type;
151: this .enumeratedType = enumeratedType;
152: this .defaultType = defaultType;
153: this .defaultValue = defaultValue;
154: }
155:
156: /** Creates new TreeAttlistDeclAttributeDef -- copy constructor. */
157: protected TreeAttlistDeclAttributeDef(
158: TreeAttlistDeclAttributeDef attributeDef) {
159: super (attributeDef);
160:
161: this .name = attributeDef.name;
162: this .type = attributeDef.type;
163: this .enumeratedType = arraycopy(attributeDef.enumeratedType);
164: this .defaultType = attributeDef.defaultType;
165: this .defaultValue = attributeDef.defaultValue;
166: }
167:
168: //
169: // itself
170: //
171:
172: /**
173: */
174: private String[] arraycopy(String[] array) {
175: if (array == null)
176: return null;
177:
178: int length = array.length;
179: String[] arrayCopy = new String[length];
180: System.arraycopy(array, 0, arrayCopy, 0, length);
181:
182: return arrayCopy;
183: }
184:
185: //
186: // from TreeObject
187: //
188:
189: /**
190: */
191: public Object clone() {
192: return new TreeAttlistDeclAttributeDef(this );
193: }
194:
195: /**
196: */
197: public boolean equals(Object object, boolean deep) {
198: if (!!!super .equals(object, deep))
199: return false;
200:
201: TreeAttlistDeclAttributeDef peer = (TreeAttlistDeclAttributeDef) object;
202: if (!!!Util.equals(this .name, peer.name))
203: return false;
204: if (this .type != peer.type)
205: return false;
206: if (!!!Util.equals(this .enumeratedType, peer.enumeratedType))
207: return false;
208: if (this .defaultType != peer.defaultType)
209: return false;
210: if (!!!Util.equals(this .defaultValue, peer.defaultValue))
211: return false;
212:
213: return true;
214: }
215:
216: /*
217: * Merge name, type, enumeration, default type and default value properties.
218: */
219: public void merge(TreeObject treeObject)
220: throws CannotMergeException {
221: super .merge(treeObject);
222:
223: TreeAttlistDeclAttributeDef peer = (TreeAttlistDeclAttributeDef) treeObject;
224: setNameImpl(peer.getName());
225: setDefaultTypeImpl(peer.getDefaultType(), peer
226: .getDefaultValue());
227: setTypeImpl(peer.getType(), peer.getEnumeratedType());
228: }
229:
230: //
231: // context
232: //
233:
234: /**
235: */
236: public final void removeFromContext() throws ReadOnlyException {
237: if (isInContext()) {
238: getOwnerAttlistDecl().removeAttributeDef(this .getName());
239: }
240: }
241:
242: //
243: // itself
244: //
245:
246: /**
247: */
248: public final TreeAttlistDecl getOwnerAttlistDecl() {
249: return (TreeAttlistDecl) getNodeDecl();
250: }
251:
252: //
253: // name
254: //
255:
256: /**
257: */
258: public final String getElementName() {
259: if (getNodeDecl() == null)
260: return null;
261: return getOwnerAttlistDecl().getElementName();
262: }
263:
264: /**
265: */
266: public final String getName() {
267: return name;
268: }
269:
270: /**
271: */
272: private final void setNameImpl(String newName) {
273: String oldName = this .name;
274:
275: this .name = newName;
276:
277: fireMapKeyChanged(oldName);
278: // firePropertyChange (PROP_NAME, oldName, newName);
279: // getNodeDecl().firePropertyChange (TreeAttlistDecl.PROP_ATTRIBUTE_DEF_MAP_CONTENT, this, this); //!!!
280: }
281:
282: /**
283: * @throws ReadOnlyException
284: * @throws InvalidArgumentException
285: */
286: public final void setName(String newName) throws ReadOnlyException,
287: InvalidArgumentException {
288: //
289: // check new value
290: //
291: if (Util.equals(this .name, newName))
292: return;
293: checkReadOnly();
294: checkName(newName);
295:
296: //
297: // set new value
298: //
299: setNameImpl(newName);
300: }
301:
302: /**
303: */
304: protected final void checkName(String name)
305: throws InvalidArgumentException {
306: TreeUtilities.checkAttlistDeclAttributeName(name);
307: }
308:
309: //
310: // type
311: //
312:
313: /**
314: */
315: public final short getType() {
316: return type;
317: }
318:
319: /**
320: */
321: public final String getTypeName() {
322: try {
323: return NAMED_TYPE_LIST[type];
324: } catch (ArrayIndexOutOfBoundsException exc) {
325: return null;
326: }
327: }
328:
329: /**
330: */
331: public final String[] getEnumeratedType() {
332: return enumeratedType;
333: }
334:
335: /**
336: */
337: public final String getEnumeratedTypeString() {
338: if (enumeratedType == null) {
339: return null;
340: }
341: StringBuffer sb = new StringBuffer();
342: sb.append("( ").append(enumeratedType[0]); // NOI18N
343: for (int i = 1; i < enumeratedType.length; i++) {
344: sb.append(" | ").append(enumeratedType[i]); // NOI18N
345: }
346: sb.append(" )"); // NOI18N
347: return sb.toString();
348: }
349:
350: public static final String[] createEnumeratedType(
351: String enumeratedType) {
352: if (Util.THIS.isLoggable()) /* then */
353: Util.THIS
354: .debug("TreeAttlistDeclAttributeDef.createEnumeratedType: enumeratedType = "
355: + enumeratedType);
356:
357: if (enumeratedType == null) {
358: return null;
359: }
360: int begin = enumeratedType.indexOf("("); // NOI18N
361: int end = enumeratedType.indexOf(")"); // NOI18N
362:
363: if (Util.THIS.isLoggable()) /* then */
364: Util.THIS.debug(" begin = " + begin);
365: if (Util.THIS.isLoggable()) /* then */
366: Util.THIS.debug(" end = " + end);
367:
368: if ((begin == -1) || (end == -1)) {
369: return null;
370: }
371: String noParenthesis = enumeratedType.substring(begin + 1, end);
372: StringTokenizer st = new StringTokenizer(noParenthesis, "|"); // NOI18N
373: List tokens = new LinkedList();
374: while (st.hasMoreTokens()) {
375: tokens.add(st.nextToken().trim());
376: }
377:
378: if (Util.THIS.isLoggable()) /* then */
379: Util.THIS.debug(" tokens = " + tokens);
380:
381: if (tokens.isEmpty())
382: return null;
383:
384: String[] arrayType = (String[]) tokens.toArray(new String[0]);
385:
386: if (Util.THIS.isLoggable()) /* then */
387: Util.THIS.debug(" RETURN arrayType = " + arrayType);
388:
389: return arrayType;
390: }
391:
392: /**
393: */
394: private final void setTypeImpl(short newType,
395: String[] newEnumeratedType) {
396: // short oldType = this.type;
397: // String[] oldEnumeratedType = this.enumeratedType;
398:
399: this .type = newType;
400: this .enumeratedType = newEnumeratedType;
401:
402: // firePropertyChange (PROP_???, old???, new???);
403: // getNodeDecl().firePropertyChange (TreeAttlistDecl.PROP_ATTRIBUTE_DEF_MAP_CONTENT, this, this); //!!!
404: }
405:
406: /**
407: * @throws ReadOnlyException
408: * @throws InvalidArgumentException
409: */
410: public final void setType(short newType, String[] newEnumeratedType)
411: throws ReadOnlyException, InvalidArgumentException {
412: if (Util.THIS.isLoggable()) /* then */
413: Util.THIS.debug("TreeAttlistDeclAttributeDef.setType");
414: if (Util.THIS.isLoggable()) /* then */
415: Util.THIS.debug(" newType = " + newType);
416: if (Util.THIS.isLoggable()) /* then */
417: Util.THIS.debug(" newEnumeratedType = "
418: + (newEnumeratedType == null ? null : Arrays
419: .asList(newEnumeratedType)));
420:
421: //
422: // check new value
423: //
424: boolean setType = this .type != newType;
425: boolean setEnumeratedType = !!!Arrays.equals(
426: this .enumeratedType, newEnumeratedType);
427:
428: if (Util.THIS.isLoggable()) /* then */
429: Util.THIS.debug(" setEnumeratedType = "
430: + setEnumeratedType);
431:
432: if (!!!setType && !!!setEnumeratedType) {
433: return;
434: }
435: checkReadOnly();
436: checkType(newType, newEnumeratedType);
437:
438: //
439: // set new value
440: //
441: setTypeImpl(newType, newEnumeratedType);
442: }
443:
444: /**
445: */
446: protected final void checkType(short type, String[] enumeratedType)
447: throws InvalidArgumentException {
448: TreeUtilities.checkAttlistDeclAttributeType(type);
449: TreeUtilities
450: .checkAttlistDeclAttributeEnumeratedType(enumeratedType);
451: }
452:
453: /**
454: */
455: public static final short findType(String type) {
456: if (Util.THIS.isLoggable()) /* then */
457: Util.THIS
458: .debug("TreeAttlistDeclAttributeDef::findType: type = "
459: + type); // NOI18N
460:
461: for (short i = 0; i < NAMED_TYPE_LIST.length; i++) {
462: if (Util.THIS.isLoggable()) /* then */
463: Util.THIS
464: .debug(" test_type = " + NAMED_TYPE_LIST[i]); // NOI18N
465:
466: if (Util.equals(NAMED_TYPE_LIST[i], type)) {
467: return i;
468: }
469: }
470: if (Util.THIS.isLoggable()) /* then */
471: Util.THIS.debug(" type[" + type + "] not found"); // NOI18N
472:
473: return -1;
474: }
475:
476: //
477: // default decl
478: //
479:
480: /**
481: */
482: public final short getDefaultType() {
483: return defaultType;
484: }
485:
486: /**
487: */
488: public final String getDefaultTypeName() {
489: try {
490: return NAMED_DEFAULT_TYPE_LIST[defaultType];
491: } catch (ArrayIndexOutOfBoundsException exc) {
492: return null;
493: }
494: }
495:
496: /**
497: */
498: public final String getDefaultValue() {
499: return defaultValue;
500: }
501:
502: /**
503: */
504: private final void setDefaultTypeImpl(short newDefaultType,
505: String newDefaultValue) {
506: // short oldDefaultType = this.defaultType;
507: // String oldDefaultValue = this.defaultValue;
508:
509: this .defaultType = newDefaultType;
510: this .defaultValue = newDefaultValue;
511:
512: // firePropertyChange (PROP_???, old???, new???);
513: // getNodeDecl().firePropertyChange (TreeAttlistDecl.PROP_ATTRIBUTE_DEF_MAP_CONTENT, this, this); //!!!
514: }
515:
516: /**
517: * @throws ReadOnlyException
518: * @throws InvalidArgumentException
519: */
520: public final void setDefaultType(short newDefaultType,
521: String newDefaultValue) throws ReadOnlyException,
522: InvalidArgumentException {
523: if (Util.THIS.isLoggable()) /* then */
524: Util.THIS
525: .debug("TreeAttlistDeclAttributeDef.setDefaultType");
526: if (Util.THIS.isLoggable()) /* then */
527: Util.THIS.debug(" newDefaultType = "
528: + NAMED_DEFAULT_TYPE_LIST[newDefaultType]);
529: if (Util.THIS.isLoggable()) /* then */
530: Util.THIS.debug(" newDefaultValue = " + newDefaultValue);
531:
532: //
533: // check new value
534: //
535: boolean setDefaultType = this .defaultType != newDefaultType;
536: boolean setDefaultValue = !!!Util.equals(this .defaultValue,
537: newDefaultValue);
538: if (!!!setDefaultType && !!!setDefaultValue) {
539: return;
540: }
541: checkReadOnly();
542: checkDefaultType(newDefaultType, newDefaultValue);
543:
544: //
545: // set new value
546: //
547: setDefaultTypeImpl(newDefaultType, newDefaultValue);
548: }
549:
550: /**
551: */
552: protected final void checkDefaultType(short defaultType,
553: String defaultValue) throws InvalidArgumentException {
554: TreeUtilities.checkAttlistDeclAttributeDefaultType(defaultType);
555: TreeUtilities
556: .checkAttlistDeclAttributeDefaultValue(defaultValue);
557: }
558:
559: /**
560: */
561: public static final short findDefaultType(String defaultType) {
562: for (short i = 0; i < NAMED_DEFAULT_TYPE_LIST.length; i++) {
563: if (Util.equals(NAMED_DEFAULT_TYPE_LIST[i], defaultType))
564: return i;
565: }
566: return -1;
567: }
568:
569: //
570: // TreeNamedObjectMap.NamedObject
571: //
572:
573: /**
574: */
575: public Object mapKey() {
576: return getName();
577: }
578:
579: /**
580: */
581: // public String mapKeyPropertyName () {
582: // return PROP_NAME;
583: // }
584: /** Attach NamedObject to NamedObject Map. */
585: public void setKeyListener(
586: TreeNamedObjectMap.KeyListener keyListener) {
587: mapKeyListener = keyListener;
588: }
589:
590: private void fireMapKeyChanged(Object oldKey) {
591: if (mapKeyListener == null) {
592: return;
593: }
594: mapKeyListener.mapKeyChanged(oldKey);
595: }
596:
597: }
|