1
2
3
4
5
6
7
8
9 package com.bbn.swede.core.dom;
10
11 import org.eclipse.jface.text.IRegion;
12
13 import com.bbn.swede.core.dom.owl.AllDifferent;
14 import com.bbn.swede.core.dom.owl.AllValuesFrom;
15 import com.bbn.swede.core.dom.owl.AnnotationProperty;
16 import com.bbn.swede.core.dom.owl.BackwardCompatibleWith;
17 import com.bbn.swede.core.dom.owl.Cardinality;
18 import com.bbn.swede.core.dom.owl.ComplementOf;
19 import com.bbn.swede.core.dom.owl.DataRange;
20 import com.bbn.swede.core.dom.owl.DatatypeProperty;
21 import com.bbn.swede.core.dom.owl.DeprecatedClass;
22 import com.bbn.swede.core.dom.owl.DeprecatedProperty;
23 import com.bbn.swede.core.dom.owl.DifferentFrom;
24 import com.bbn.swede.core.dom.owl.DisjointWith;
25 import com.bbn.swede.core.dom.owl.DistinctMembers;
26 import com.bbn.swede.core.dom.owl.EquivalentClass;
27 import com.bbn.swede.core.dom.owl.EquivalentProperty;
28 import com.bbn.swede.core.dom.owl.FunctionalProperty;
29 import com.bbn.swede.core.dom.owl.HasValue;
30 import com.bbn.swede.core.dom.owl.Imports;
31 import com.bbn.swede.core.dom.owl.IncompatibleWith;
32 import com.bbn.swede.core.dom.owl.IntersectionOf;
33 import com.bbn.swede.core.dom.owl.InverseFunctionalProperty;
34 import com.bbn.swede.core.dom.owl.InverseOf;
35 import com.bbn.swede.core.dom.owl.MaxCardinality;
36 import com.bbn.swede.core.dom.owl.MinCardinality;
37 import com.bbn.swede.core.dom.owl.ObjectProperty;
38 import com.bbn.swede.core.dom.owl.OnProperty;
39 import com.bbn.swede.core.dom.owl.OneOf;
40 import com.bbn.swede.core.dom.owl.Ontology;
41 import com.bbn.swede.core.dom.owl.OntologyProperty;
42 import com.bbn.swede.core.dom.owl.PriorVersion;
43 import com.bbn.swede.core.dom.owl.Restriction;
44 import com.bbn.swede.core.dom.owl.SameAs;
45 import com.bbn.swede.core.dom.owl.SomeValuesFrom;
46 import com.bbn.swede.core.dom.owl.SymmetricProperty;
47 import com.bbn.swede.core.dom.owl.Thing;
48 import com.bbn.swede.core.dom.owl.TransitiveProperty;
49 import com.bbn.swede.core.dom.owl.UnionOf;
50 import com.bbn.swede.core.dom.owl.VersionInfo;
51 import com.bbn.swede.core.dom.rdf.Description;
52 import com.bbn.swede.core.dom.rdf.First;
53 import com.bbn.swede.core.dom.rdf.List;
54 import com.bbn.swede.core.dom.rdf.Property;
55 import com.bbn.swede.core.dom.rdf.Rdf;
56 import com.bbn.swede.core.dom.rdf.Rest;
57 import com.bbn.swede.core.dom.rdf.Type;
58 import com.bbn.swede.core.dom.rdfs.Comment;
59 import com.bbn.swede.core.dom.rdfs.Domain;
60 import com.bbn.swede.core.dom.rdfs.Label;
61 import com.bbn.swede.core.dom.rdfs.Range;
62 import com.bbn.swede.core.dom.rdfs.SeeAlso;
63 import com.bbn.swede.core.dom.rdfs.SubClassOf;
64 import com.bbn.swede.core.dom.rdfs.SubPropertyOf;
65
66 /***
67 * Common implementation for nodes representing XML tags.
68 * @author jlerner
69 */
70 public abstract class TagNode extends OASTNode
71 {
72 /***
73 * Creates a parentless tag node with discrete begin and end tags.
74 */
75 public TagNode()
76 {
77 initRegions(false);
78 }
79
80 /***
81 * Creates a parentless tag node. The tag will be either a singleton or
82 * discrete begin and end tags depending on the parameter passed. A
83 * singleton tag node will be split into begin and end tags automatically if
84 * a non-attribute child is added to it later.
85 * @param bSingleton <code>true</code> to create a singleton tag,
86 * <code>false</code> to create discrete begin and end tags.
87 */
88 public TagNode(boolean bSingleton)
89 {
90 initRegions(bSingleton);
91 }
92
93 /***
94 * Initializes the simple partitioning of the tag node.
95 * @param bSingleton <code>true</code> to partition the tag as a singleton,
96 * <code>false</code> to partition it as discrete begin
97 * and end tags.
98 */
99 protected void initRegions(boolean bSingleton)
100 {
101 if (bSingleton)
102 {
103 createSingletonRegion();
104 }
105 else
106 {
107 createRegions();
108 }
109 }
110
111 /***
112 * Creates a begin region for the node, marking it as a singleton. The
113 * length of the node will also be set to match the size of the singleton
114 * region.
115 */
116 protected void createSingletonRegion()
117 {
118 String sQName = getQName();
119
120
121 if (sQName == null)
122 {
123 return;
124 }
125 _iLength = sQName.length() + 3;
126 setBeginRegion(_iLength);
127 _drMiddle = _drEnd = null;
128 _regions = new IRegion[]{_drBegin};
129 }
130
131 /***
132 * Creates regions for the begin and end tags of the node. The length of
133 * the node will be set to match the combined size of the regions.
134 */
135 protected void createRegions()
136 {
137 String sQName = getQName();
138
139
140 if (sQName == null)
141 {
142 return;
143 }
144 int iLength = sQName.length() + 2;
145 _iLength = iLength * 2 + 1;
146 setBeginRegion(iLength);
147
148
149 setEndRegion(iLength);
150 }
151
152 private DisplaceableRegion _drBegin;
153 private DisplaceableRegion _drMiddle;
154 private DisplaceableRegion _drEnd;
155 private IRegion[] _regions;
156
157
158
159
160 public IRegion[] simplePartitioning()
161 {
162 return _regions;
163 }
164
165 /***
166 * Indicates whether this tag node represents a singleton tag.
167 * @return <code>true</code> if the tag is a singleton, <code>false</code>
168 * if it has begin and end tags.
169 */
170 protected boolean isSingleton()
171 {
172 return (_drEnd == null);
173 }
174
175 /***
176 * Sets the begin region of the tag-based node's simple partitioning. The
177 * offset of the region is based on the node's starting offset as returned
178 * by getOffset()
179 * @param length The length of the beginning region. This is assumed to be
180 * less than or equal to the total length of the node, though this
181 * method may be called before the node length has been set.
182 */
183 protected void setBeginRegion(int length)
184 {
185 _drBegin = new DisplaceableRegion(getOffset(), length, true);
186 }
187
188 /***
189 * Sets the end region of the tag-based node's simple partitioning. The
190 * length of the end region is calculated automatically based on the values
191 * returned by getOffset() and getLength(). A middle region will be
192 * created automatically if there is a gap between the beginning and end
193 * regions.
194 * @param offset Starting offset of the end region. Must be greater than
195 * or equal to the offset plus the length of the begin region.
196 */
197 protected void setEndRegion(int offset)
198 {
199 int length = getOffset() + getLength() - offset;
200 if (length <= 0)
201 {
202 _drMiddle = null;
203 _drEnd = null;
204 _regions = new IRegion[] {_drBegin};
205 return;
206 }
207 _drEnd = new DisplaceableRegion(offset, length, true);
208 if (_drBegin.getOffset() + _drBegin.getLength() == offset)
209 {
210 _drMiddle = null;
211 _regions = new IRegion[] {_drBegin, _drEnd};
212 return;
213 }
214 _drMiddle =
215 new DisplaceableRegion(
216 _drBegin.getOffset() + _drBegin.getLength(),
217 getLength() - _drBegin.getLength() - _drEnd.getLength());
218 _regions = new IRegion[] {_drBegin, _drMiddle, _drEnd};
219 }
220
221
222
223
224
225 public boolean displace(int offset, int length)
226 {
227 if (!super.displace(offset, length))
228 {
229 return false;
230 }
231
232 if (_drBegin != null)
233 {
234 _drBegin.displace(offset, length);
235 }
236 if (_drMiddle != null)
237 {
238 _drMiddle.displace(offset, length);
239 }
240 if (_drEnd != null)
241 {
242 if (_drMiddle == null && _drEnd.getOffset() == offset)
243 {
244 _drMiddle = new DisplaceableRegion(offset, length, true);
245
246 _regions = new IRegion[]{_drBegin, _drMiddle, _drEnd};
247 }
248 _drEnd.displace(offset, length);
249 }
250
251 return true;
252 }
253
254 /***
255 * Adds an attribute to the tag, after all existing attributes. The tag
256 * must not already contain an attribute with the same QName.
257 * @param sQName the qualified name of the attribute to add
258 * @param sValue the value of the attribute to add. If this is an empty
259 * string, the attribute will be added with an empty value.
260 * If it is <code>null</code>, the attribute will not be added.
261 * @throws OASTException if this node is attached to a read-only OAST or
262 * the attribute is already defined for this object.
263 */
264 public void addAttribute(String sQName, String sValue) throws OASTException
265 {
266 if (sValue == null)
267 {
268 return;
269 }
270 AttributeNode att = getAttribute(sQName);
271 if (att != null)
272 {
273 throw new OASTException("Node already has an attribute with that qname", this);
274 }
275 synchronized (getLockObject())
276 {
277 att = AttributeNode.create(sQName, sValue);
278
279 int iOffset = 0;
280 AttributeNode attLast = getLastAttribute();
281 if (attLast != null)
282 {
283 iOffset = attLast.getOffset() + attLast.getLength();
284 }
285 else
286 {
287 iOffset = _drBegin.getOffset() + _drBegin.getLength();
288 iOffset -= (isSingleton() ? 2 : 1);
289 }
290 att.accept(new NodeDisplacementVisitor(0, iOffset));
291 insert(att, true);
292 }
293 }
294
295 /***
296 * Sets the value of a child attribute of this tag. If the tag does not
297 * already have an attribute with the specified qname, one will be added.
298 * @param sQName the qualified name of the attribute to set or add
299 * @param sValue the new value of the attribute. If this is an empty
300 * string, the attribute will be given an empty value.
301 * If it is <code>null</code>, the attribute will be removed.
302 * @throws OASTException if this node is attached to a read-only OAST
303 */
304 public void setAttribute(String sQName, String sValue) throws OASTException
305 {
306 if (sValue == null)
307 {
308 removeAttribute(sQName);
309 return;
310 }
311 AttributeNode att = getAttribute(sQName);
312 if (att == null)
313 {
314 addAttribute(sQName, sValue);
315 }
316 else
317 {
318 att.setValue(sValue);
319 }
320 }
321
322 /***
323 * Retrieves a child attribute with a specified QName.
324 * @param sQName the qualified name of the attribute to retrieve
325 * @return The requested attribute, or <code>null</code> if this tag
326 * does not have an attribute with with that qname.
327 */
328 public AttributeNode getAttribute(String sQName)
329 {
330 OASTNode[] children = getChildren();
331 OASTNode node = null;
332 AttributeNode attr = null;
333 AttributeNode toReturn = null;
334 for (int i = 0; i < children.length; i++)
335 {
336 node = children[i];
337 if(node instanceof AttributeNode)
338 {
339 attr = (AttributeNode) node;
340 if (attr.getQName().equals(sQName))
341 {
342 toReturn = attr;
343 break;
344 }
345 }
346 }
347 return toReturn;
348 }
349
350 /***
351 * Retrieves all the attributes of this tag.
352 * @return An array of AttributeNodes that are children of this tag. If the
353 * tag has no attributes, an empty array is returned.
354 */
355 public AttributeNode[] getAttributes()
356 {
357 AttributeNode last = getLastAttribute();
358 if (last == null)
359 {
360 return new AttributeNode[0];
361 }
362
363 OASTNode[] children = getChildren();
364 int index = 0;
365 while (children[index] != last)
366 {
367 index++;
368 }
369 AttributeNode[] attributes = new AttributeNode[index + 1];
370 for (int i = 0; i < attributes.length; i++)
371 {
372 attributes[i] = (AttributeNode)children[i];
373 }
374
375 return attributes;
376 }
377
378 /***
379 * <p>Removes an attribute from the tag. If the tag does not have an
380 * attribute with the specified QName, there is no effect.</p>
381 *
382 * <p>This is a convenience method, fully equivalent to:
383 * <blockquote>removeAttribute(getAttribute(sQName))</blockquote></p>
384 * @param sQName the qualified name of the attribute to remove
385 * @throws OASTException if this node is attached to a read-only OAST
386 */
387 public void removeAttribute(String sQName) throws OASTException
388 {
389 removeAttribute(getAttribute(sQName));
390 }
391
392 /***
393 * Removes an attribute from the tag.
394 * @param attribute the attribute node to remove
395 * @throws OASTException if this node is attached to a read-only OAST
396 */
397 public void removeAttribute(AttributeNode attribute) throws OASTException
398 {
399 if (attribute == null)
400 {
401 return;
402 }
403 else
404 {
405 remove(attribute, true);
406 }
407 }
408
409 /***
410 * <p>Changes the tag from a singleton to discrete begin and end tags. If
411 * the tag is connected to an OWL Abstract Syntax Tree, this node will be
412 * replaced to ensure that the editor updates its text properly. As a
413 * result, callers should use the return value of this method for
414 * any further changes they need to make to the tag, since this instance
415 * may no longer be valid after the split.</p>
416 *
417 * <p>Whenever possible, callers should also wrap calls to
418 * <code>splitSingleton</code> and their other OAST processing in an OAST
419 * runnable so that only one event notification is sent to OAST change
420 * listeners.</p>
421 *
422 * <p>If this tag is not a singleton, it will simply be returned without
423 * making any changes to the OAST.</p>
424 * @see IOASTRunnable
425 * @see IOWLAbstractSyntaxTree#run(IOASTRunnable)
426 * @return The resulting non-singleton tag
427 * @throws OASTException if this node is attached to a read-only OAST
428 */
429 protected TagNode splitSingleton() throws OASTException
430 {
431 if (!isSingleton())
432 {
433 return this;
434 }
435
436 if (getOWLAbstractSyntaxTree() == null)
437 {
438
439
440
441
442
443
444 _iLength = _drBegin.getLength() + getQName().length() + 2;
445 _drBegin.displace(_drBegin.getOffset() + _drBegin.getLength() - 1, -1);
446 setEndRegion(_drBegin.getOffset() + _drBegin.getLength());
447 return this;
448 }
449 else
450 {
451
452 TagNode tag = TagNode.create(getQName(), getParent());
453 if (tag.isSingleton())
454 {
455 tag.splitSingleton();
456 }
457 AttributeNode[] attributes = getAttributes();
458 for(int i = 0; i < attributes.length; i++)
459 {
460 tag.addAttribute(attributes[i].getQName(), attributes[i].getValue());
461 }
462 tag.accept(new NodeDisplacementVisitor(0, getOffset()));
463 getParent().replace(this, tag);
464 return tag;
465 }
466 }
467
468 /***
469 * Inserts a tag node as the first non-attribute child of this node. If
470 * the tag is a singleton, it will be split into discrete begin/end tags
471 * first. The insertion position will be immediately after the begin tag
472 * of this node. The child node will be displaced to the target offset
473 * and the tree containing this node will be displaced to make
474 * room for the inserted child.
475 * @param child The tag node to add as a child
476 * @throws OASTException if this node is attached to a read-only OAST
477 */
478 public void prependChildTag(final TagNode child) throws OASTException
479 {
480 IOASTRunnable action = new DefaultOASTRunnable()
481 {
482
483
484
485 public void run() throws OASTException
486 {
487 TagNode tag = splitSingleton();
488
489 int iOffset = tag._drBegin.getOffset() + tag._drBegin.getLength();
490 child.accept(new NodeDisplacementVisitor(0, iOffset));
491 tag.insert(child, true);
492 }
493 };
494 if (getOWLAbstractSyntaxTree() != null)
495 {
496 getOWLAbstractSyntaxTree().run(action);
497 }
498 else
499 {
500 action.run();
501 }
502 }
503
504 /***
505 * Inserts a tag node as the last non-attribute child of this node. If
506 * the tag is a singleton, it will be split into discrete begin/end tags
507 * first. The insertion position will be immediately before the end tag
508 * of this node. The child node will be displaced to the target offset
509 * and the tree containing this node will be displaced to make
510 * room for the inserted child.
511 * @param child The tag node to add as a child
512 * @throws OASTException if this node is attached to a read-only OAST
513 */
514 public void appendChildTag(final TagNode child) throws OASTException
515 {
516 IOASTRunnable action = new DefaultOASTRunnable()
517 {
518
519
520
521 public void run() throws OASTException
522 {
523 TagNode tag = splitSingleton();
524
525 int iOffset = tag._drEnd.getOffset();
526 child.accept(new NodeDisplacementVisitor(0, iOffset));
527 tag.insert(child, true);
528 }
529 };
530 if (getOWLAbstractSyntaxTree() != null)
531 {
532 getOWLAbstractSyntaxTree().run(action);
533 }
534 else
535 {
536 action.run();
537 }
538 }
539
540 /***
541 * Inserts an attribute node as the first attribute child of this node. The
542 * insertion position will be immediately after the qname in this node's
543 * begin tag, plus one character of whitespace. The child node will be
544 * displaced to the target offset and the tree containing this node will be
545 * displaced to make room for the inserted child.
546 * @param child The attribute node to add as a child
547 * @throws OASTException if this node is attached to a read-only OAST
548 */
549 public void prependChildAttribute(AttributeNode child) throws OASTException
550 {
551 int iOffset = _drBegin.getOffset() + getQName().length() + 1;
552 child.accept(new NodeDisplacementVisitor(0, iOffset));
553 insert(child, true);
554 }
555
556
557
558
559
560 public String generateNodeText()
561 {
562 StringBuffer sb = new StringBuffer(getLength());
563 for (int i = 0; i < sb.capacity(); i++)
564 {
565 sb.append(' ');
566 }
567
568
569 int iOffset = _drBegin.getOffset() - _iOffset;
570 sb.replace(iOffset, iOffset + 1, "<");
571 iOffset++;
572 String s = getQName();
573 sb.replace(iOffset, iOffset + s.length(), s);
574 if (isSingleton())
575 {
576 iOffset = _drBegin.getOffset() + _drBegin.getLength() - _iOffset - 2;
577 sb.replace(iOffset, iOffset + 2, "/>");
578 }
579 else
580 {
581 iOffset = _drBegin.getOffset() + _drBegin.getLength() - _iOffset - 1;
582 sb.replace(iOffset, iOffset + 1, ">");
583 iOffset = _drEnd.getOffset() - _iOffset;
584 sb.replace(iOffset, iOffset + s.length() + 3, "</" + s + ">");
585 }
586
587
588
589 OASTNode[] children = getChildren();
590 for (int i = 0; i < children.length; i++)
591 {
592 OASTNode node = children[i];
593 iOffset = node.getOffset() - _iOffset;
594 s = node.generateNodeText();
595 sb.replace(iOffset, iOffset + s.length(), s);
596 }
597
598 return sb.toString();
599 }
600 /***
601 * Inserts an attribute node as the last attribute child of this node. The
602 * insertion position will be immediately before the '>' or '/>' terminating
603 * this node's begin tag. The child node will be
604 * displaced to the target offset and the tree containing this node will be
605 * displaced to make room for the inserted child, plus one character of
606 * whitespace to separate the new attribute from the previous one.
607 * @param child The attribute node to add as a child
608 * @throws OASTException if this node is attached to a read-only OAST
609 */
610 public void appendChildAttribute(AttributeNode child) throws OASTException
611 {
612 int iOffset = _drBegin.getOffset() + _drBegin.getLength();
613 if (isSingleton())
614 {
615 iOffset -= 2;
616 }
617 else
618 {
619 iOffset--;
620 }
621 child.accept(new NodeDisplacementVisitor(0, iOffset));
622 insert(child, true);
623 }
624
625
626
627
628
629 protected OASTNode duplicateType()
630 {
631 OASTNode newTag = TagNode.create(getQName(), getParent());
632 if (newTag != null)
633 {
634 return newTag;
635 }
636 else if (getNodeType() == OASTNode.GENERICTHING)
637 {
638 return new GenericThing(getQName());
639 }
640 else if (getNodeType() == OASTNode.GENERICPREDICATE)
641 {
642 return new GenericPredicate(getQName());
643 }
644
645 return null;
646 }
647
648
649
650
651
652 public Object clone()
653 {
654 TagNode newTag = (TagNode)super.clone();
655 newTag._drBegin = new DisplaceableRegion(_drBegin.getOffset(), _drBegin.getLength(), _drBegin.moveIfEqual());
656 newTag._drMiddle = (_drMiddle == null ? null
657 : new DisplaceableRegion(_drMiddle.getOffset(), _drMiddle.getLength(), _drMiddle.moveIfEqual()));
658 newTag._drEnd = (_drEnd == null ? null
659 : new DisplaceableRegion(_drEnd.getOffset(), _drEnd.getLength(), _drEnd.moveIfEqual()));
660 int iLength = 1;
661 if (newTag._drEnd != null)
662 {
663 iLength++;
664 }
665 if (newTag._drMiddle != null)
666 {
667 iLength++;
668 }
669 newTag._regions = new IRegion[iLength];
670 newTag._regions[0] = newTag._drBegin;
671 if (newTag._drMiddle != null)
672 {
673 newTag._regions[1] = newTag._drMiddle;
674 }
675 if (newTag._drEnd != null)
676 {
677 newTag._regions[iLength - 1] = newTag._drEnd;
678 }
679 return newTag;
680 }
681
682 /***
683 * Factory method for creating tag nodes. Returns a node of the specified
684 * type with no parent and no children.
685 * @param iNodeType A node type constant specifying a tag type. This
686 * includes all RDF_, RDFS_, and OWL_ node types not handled by
687 * AttributeNode.create().
688 * @see AttributeNode#create(int, String)
689 * @return A node of the specified type, or <code>null</code> if an unknown
690 * or non-tag node type is specified.
691 */
692 private static TagNode create(int iNodeType)
693 {
694 switch (iNodeType)
695 {
696 case RDF_RDF :
697 return new Rdf();
698 case RDF_DESCRIPTION :
699 return new Description();
700 case RDF_PROPERTY :
701 return new Property();
702 case RDF_LIST :
703 return new List();
704 case RDF_TYPE :
705 return new Type();
706 case RDF_FIRST :
707 return new First();
708 case RDF_REST :
709 return new Rest();
710 case RDFS_SUBCLASSOF :
711 return new SubClassOf();
712 case RDFS_COMMENT :
713 return new Comment();
714 case RDFS_LABEL :
715 return new Label();
716 case RDFS_CLASS :
717 return new com.bbn.swede.core.dom.rdfs.Klass();
718 case RDFS_SUBPROPERTYOF :
719 return new SubPropertyOf();
720 case RDFS_DOMAIN :
721 return new Domain();
722 case RDFS_RANGE :
723 return new Range();
724 case RDFS_SEEALSO :
725 return new SeeAlso();
726 case OWL_CLASS :
727 return new com.bbn.swede.core.dom.owl.Klass();
728 case OWL_DATATYPEPROPERTY :
729 return new DatatypeProperty();
730 case OWL_OBJECTPROPERTY :
731 return new ObjectProperty();
732 case OWL_RESTRICTION :
733 return new Restriction();
734 case OWL_ONPROPERTY :
735 return new OnProperty();
736 case OWL_ALLDIFFERENT :
737 return new AllDifferent();
738 case OWL_ANNOTATIONPROPERTY :
739 return new AnnotationProperty();
740 case OWL_DATARANGE :
741 return new DataRange();
742 case OWL_DEPRECATEDCLASS :
743 return new DeprecatedClass();
744 case OWL_DEPRECATEDPROPERTY :
745 return new DeprecatedProperty();
746 case OWL_FUNCTIONALPROPERTY :
747 return new FunctionalProperty();
748 case OWL_INVERSEFUNCTIONALPROPERTY :
749 return new InverseFunctionalProperty();
750 case OWL_ONTOLOGY :
751 return new Ontology();
752 case OWL_ONTOLOGYPROPERTY :
753 return new OntologyProperty();
754 case OWL_SYMMETRICPROPERTY :
755 return new SymmetricProperty();
756 case OWL_THING :
757 return new Thing();
758 case OWL_TRANSITIVEPROPERTY :
759 return new TransitiveProperty();
760 case OWL_ALLVALUESFROM :
761 return new AllValuesFrom();
762 case OWL_BACKWARDCOMPATIBLEWITH :
763 return new BackwardCompatibleWith();
764 case OWL_CARDINALITY :
765 return new Cardinality();
766 case OWL_COMPLEMENTOF :
767 return new ComplementOf();
768 case OWL_DIFFERENTFROM :
769 return new DifferentFrom();
770 case OWL_DISJOINTWITH :
771 return new DisjointWith();
772 case OWL_DISTINCTMEMBERS :
773 return new DistinctMembers();
774 case OWL_EQUIVALENTCLASS :
775 return new EquivalentClass();
776 case OWL_EQUIVALENTPROPERTY :
777 return new EquivalentProperty();
778 case OWL_HASVALUE :
779 return new HasValue();
780 case OWL_IMPORTS :
781 return new Imports();
782 case OWL_INCOMPATIBLEWITH :
783 return new IncompatibleWith();
784 case OWL_INTERSECTIONOF :
785 return new IntersectionOf();
786 case OWL_INVERSEOF :
787 return new InverseOf();
788 case OWL_MAXCARDINALITY :
789 return new MaxCardinality();
790 case OWL_MINCARDINALITY :
791 return new MinCardinality();
792 case OWL_ONEOF :
793 return new OneOf();
794 case OWL_PRIORVERSION :
795 return new PriorVersion();
796 case OWL_SAMEAS :
797 return new SameAs();
798 case OWL_SOMEVALUESFROM :
799 return new SomeValuesFrom();
800 case OWL_UNIONOF :
801 return new UnionOf();
802 case OWL_VERSIONINFO :
803 return new VersionInfo();
804 default :
805 return null;
806 }
807 }
808
809 /***
810 * <p>Factory method for creating tag nodes. If the specified QName is
811 * recognized as a tag from the RDF, RDFS, or OWL language, a custom node
812 * of the appropriate type will be returned.</p>
813 *
814 * <p>Optionally, a parent node may be specified. No parent/child relationships
815 * are created, but if an unrecognized QName is specified the parent node
816 * will be used to determine which kind of generic tag to create in order
817 * to maintain proper thing/predicate striping.</p>
818 *
819 * <p>If no parent and a non-language qname are provided, no node will be
820 * created.</p>
821 * @param sQName The qualified name for the tag node
822 * @param parent The intended parent of the new node, or <code>null</code>
823 * @return A tag node of the specified type, a generic predicate or thing,
824 * or <code>null</code> if the appropriate generic type cannot be
825 * determined.
826 */
827 public static TagNode create(String sQName, OASTNode parent)
828 {
829 int iPos = sQName.indexOf(':');
830 if (iPos < 0)
831 {
832 if (parent == null)
833 {
834 return null;
835 }
836 else if (parent instanceof PropertyNode || parent instanceof Rdf)
837 {
838 return new GenericThing(sQName);
839 }
840 else
841 {
842 return new GenericPredicate(sQName);
843 }
844 }
845
846 String sNS = sQName.substring(0, iPos);
847 String sName = sQName.substring(iPos + 1);
848 int iNodeType = 0;
849 int iBase = -1;
850 String[] asTags = null;
851 if (sNS.equals("rdf"))
852 {
853 iBase = RDF;
854 asTags = AS_RDF;
855 }
856 else if (sNS.equals("rdfs"))
857 {
858 iBase = RDFS;
859 asTags = AS_RDFS;
860 }
861 else if (sNS.equals("owl"))
862 {
863 iBase = OWL;
864 asTags = AS_OWL;
865 }
866
867 if (iBase >= 0)
868 {
869 int i;
870 for (i = 0; i < asTags.length; i++)
871 {
872 if (asTags[i].equals(sName))
873 {
874 break;
875 }
876 }
877 OASTNode nodeReturn = null;
878 if (i < asTags.length)
879 {
880 iNodeType = iBase + i;
881 nodeReturn = TagNode.create(iNodeType);
882 }
883 if (i >= asTags.length || nodeReturn == null)
884 {
885 if (parent == null)
886 {
887 return null;
888 }
889 else if (parent instanceof PropertyNode || parent instanceof Rdf)
890 {
891 nodeReturn = new GenericThing(sQName);
892 }
893 else
894 {
895 nodeReturn = new GenericPredicate(sQName);
896 }
897 }
898
899 return (TagNode)nodeReturn;
900 }
901
902 if (parent == null)
903 {
904 return null;
905 }
906 else if (parent instanceof PropertyNode || parent instanceof Rdf)
907 {
908 return new GenericThing(sQName);
909 }
910 else
911 {
912 return new GenericPredicate(sQName);
913 }
914 }
915
916 /***
917 * <p>Factory method for creating language tag nodes. Returns a node of the
918 * specified type with no parent and no children. If a non-language
919 * qname or the qname of a non-tag language element is specified, no node
920 * will be created.</p>
921 *
922 * <p>This is a convenience method, fully equivalent to:
923 * <blockquote>create(sQName, null)</blockquote></p>
924 * @param sQName A string specifying a qualified name for the node
925 * @return A node with the specified qname, or <code>null</code> if an
926 * unknown or non-tag node qname is specified.
927 */
928 public static TagNode create(String sQName)
929 {
930 return create(sQName, null);
931 }
932 }