1 /** 2 * Redistribution and use of this software and associated documentation ("Software"), with or 3 * without modification, are permitted provided that the following conditions are met: 4 * 5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions 6 * must also contain a copy of this document. 7 * 8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 9 * conditions and the following disclaimer in the documentation and/or other materials provided with 10 * the distribution. 11 * 12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software 13 * without prior written permission of Intalio, Inc. For written permission, please contact 14 * info@exolab.org. 15 * 16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in 17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of 18 * Intalio, Inc. 19 * 20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/). 21 * 22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright 1999-2004 (C) Intalio, Inc. All Rights Reserved. 32 * 33 * $Id$ 34 */ 35 36 package org.exolab.castor.xml.schema; 37 38 import java.util.Enumeration; 39 40 import org.exolab.castor.xml.ValidationException; 41 42 /** 43 * The XML Schema ComplexType class. 44 * 45 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 46 * @version $Revision$ $Date: 2006-02-01 15:47:48 -0700 (Wed, 01 Feb 2006) $ 47 */ 48 public class ComplexType extends XMLType implements ContentModelGroup, Referable { 49 /** SerialVersionUID */ 50 private static final long serialVersionUID = 5348120259072084658L; 51 52 /** 53 * The abstract flag for this ComplexType. 54 */ 55 private boolean _abstract = false; 56 57 /** 58 * A wildcard that represents an {@literal <anyAttribute>} element if any. Only one {@literal 59 * <anyAttribute>} can appear inside the global scope of a complexType 60 */ 61 private Wildcard _anyAttribute = null; 62 63 /** 64 * The attribute declarations for this ComplexType. 65 */ 66 private AttributeGroupDecl _attributes = null; 67 68 /** 69 * The name of the base type used in <restriction>> or <extension>. 70 */ 71 private String _baseType = null; 72 73 /** 74 * The value of the 'block' property for this ComplexType. This value may be null. 75 */ 76 private BlockList _block = null; 77 78 /** 79 * a flag set to true if this complexType is a complexContent. 80 */ 81 private boolean _complexContent = true; 82 83 /** 84 * The content type ("mixed", "simpleType","elemOnly") for this ComplexType. 85 */ 86 private ContentType _content = ContentType.elemOnly; 87 88 /** 89 * The ContentModel for this ComplexType. 90 */ 91 private ContentModelGroup _contentModel = null; 92 93 /** 94 * The final property for this ComplexType. This value may be null.. 95 */ 96 private FinalList _final = null; 97 98 /** 99 * The parent structure for this {@link ComplexType} (either an {@link ElementDecl} or a 100 * {@link Schema}). 101 */ 102 private Structure _parent = null; 103 104 /** 105 * a flag set to true if this complexType is a restriction. 106 */ 107 private boolean _restricted = false; 108 109 /** 110 * An attribute that indicates if this ComplexType is a redefinition. 111 */ 112 private boolean _redefinition = false; 113 114 // ------------------/ 115 // - Constructor(s) -/ 116 // ------------------/ 117 118 /** 119 * Creates a new {@link ComplexType} instance with no name. 120 * 121 * @param schema the owning {@link Schema} document 122 */ 123 public ComplexType(final Schema schema) { 124 this(schema, null); 125 } // -- Complextype 126 127 /** 128 * Creates a new {@link ComplexType} with the given name. 129 * 130 * @param schema The owning {@link Schema} instance 131 * @param name Name of the {@link ComplexType} 132 */ 133 public ComplexType(final Schema schema, final String name) { 134 super(); 135 if (schema == null) { 136 String err = NULL_ARGUMENT + "; 'schema' must not be null."; 137 throw new IllegalArgumentException(err); 138 } 139 140 setSchema(schema); 141 setName(name); 142 _attributes = new AttributeGroupDecl(schema); 143 _contentModel = new ContentModelGroupImpl(); 144 } // -- Complextype 145 146 /** 147 * Adds the given {@link AttributeDecl} to this {@link ComplexType}. 148 * 149 * @param attrDecl the {@link AttributeDecl} to add to this {@link ComplexType} 150 */ 151 public void addAttributeDecl(final AttributeDecl attrDecl) { 152 _attributes.addAttribute(attrDecl); 153 154 // --set the parent 155 attrDecl.setParent(this); 156 } // -- addAttributeDecl 157 158 /** 159 * Removes the given {@link AttributeDecl} from this {@link ComplexType}. 160 * 161 * @param attrDecl the AttributeDecl to remove. 162 */ 163 public void removeAttributeDecl(final AttributeDecl attrDecl) { 164 _attributes.removeAttribute(attrDecl); 165 } 166 167 /** 168 * Adds the given AttributeGroupReference to this ComplexType. 169 * 170 * @param attrGroupRef the AttributeGroupReference to add to this ComplexType 171 */ 172 public void addAttributeGroupReference(final AttributeGroupReference attrGroupRef) { 173 _attributes.addReference(attrGroupRef); 174 } // -- addAttributeGroupReference 175 176 /** 177 * Removes the given {@link AttributeGroupReference} from this {@link ComplexType}. 178 * 179 * @param attrGroupRef the {@link AttributeGroupReference} to remove. 180 */ 181 public void removeAttributeGroupReference(final AttributeGroupReference attrGroupRef) { 182 _attributes.removeReference(attrGroupRef); 183 } 184 185 /** 186 * Creates an {@link AttributeDecl} with the given name. The attribute declaration will still need 187 * to be added to this {@link ComplexType}, or another archetype in the same schema, by making a 188 * call to #addAttributeDecl 189 * 190 * @param name the name of the attribute 191 * @return the new AttributeDecl 192 */ 193 public AttributeDecl createAttributeDecl(final String name) { 194 return new AttributeDecl(getSchema(), name); 195 } // -- createAttributeDecl 196 197 /** 198 * Returns the wilcard used in this complexType (can be null). 199 * 200 * @return the wilcard used in this complexType (can be null) 201 */ 202 public Wildcard getAnyAttribute() { 203 return _anyAttribute; 204 } 205 206 /** 207 * Returns the {@link AttributeDecl} associated with the given name. 208 * 209 * @param name Name of the associated {@link AttributeDecl} 210 * 211 * @return the {@link AttributeDecl} associated with the given name, or null if no 212 * {@link AttributeDecl} with the given name was found. 213 */ 214 public AttributeDecl getAttributeDecl(final String name) { 215 AttributeDecl result = _attributes.getAttribute(name); 216 return result; 217 } // -- getAttributeDecl 218 219 /** 220 * Returns an Enumeration of *all* the AttributeDecl objects declared within this ComplexType. The 221 * Enumeration will contain all AttributeDecl from AttributeGroup references as well. To return 222 * only locally declared attributes make a call to <code>getLocalAttributeDecls</code>. 223 * 224 * @return an Enumeration of all the AttributeDecl objects declared within this Complextype 225 */ 226 public Enumeration<AttributeDecl> getAttributeDecls() { 227 return _attributes.getAttributes(); 228 } // -- getAttributeDecls 229 230 /** 231 * Returns an Enumeration of *all* locally defined AttributeDecl declared within this ComplexType. 232 * The Enumeration will not contain any AttributeDecl from AttributeGroup references. 233 * 234 * @return an Enumeration of all locally declared AttributeDecl. 235 */ 236 public Enumeration<AttributeDecl> getLocalAttributeDecls() { 237 return _attributes.getLocalAttributes(); 238 } // -- getLocalAttributeDecls 239 240 /** 241 * Returns an Enumeration of all the AttributeGroup that are referenced within this ComplexType. 242 * 243 * @return an Enumeration of all the AttributeGroup that are referenced within this ComplexType. 244 */ 245 public Enumeration<AttributeGroupReference> getAttributeGroupReferences() { 246 return _attributes.getLocalAttributeGroupReferences(); 247 } 248 249 /** 250 * Returns the base type that this type inherits from. 251 * 252 * @return the base type (also called super type). 253 */ 254 public XMLType getBaseType() { 255 if ((_baseType != null) && (super.getBaseType() == null)) { 256 XMLType baseType = getSchema().getType(_baseType); 257 setBaseType(baseType); 258 } 259 return super.getBaseType(); 260 } // -- getBaseType 261 262 /** 263 * Returns the value of the 'block' attribute for this element. 264 * 265 * @return the value of the 'block' attribute for this element 266 */ 267 public BlockList getBlock() { 268 return _block; 269 } // -- getBlock 270 271 /** 272 * Returns the content type of this ComplexType. The Content Type holds the information about the 273 * content of the complexType. For instance, if this complexType is a simpleContent then the 274 * simpleType information will be hold in the content type. 275 * 276 * @return the content type of this ComplexType 277 */ 278 public ContentType getContentType() { 279 return _content; 280 } // -- getContentType 281 282 /** 283 * Returns the list of values for the final property for this ComplexType, or null if no final 284 * values have been set. 285 * 286 * @return the FinalList for this ComplexType 287 */ 288 public FinalList getFinal() { 289 return _final; 290 } // -- getFinal 291 292 /** 293 * Returns the parent of this ComplexType, this value may be null if no parent has been set. 294 * 295 * @return the parent Structure of this ComplexType. 296 */ 297 public Structure getParent() { 298 return _parent; 299 } // -- getParent 300 301 /** 302 * Returns the Id used to Refer to this Object. 303 * 304 * @return the Id used to Refer to this Object 305 * @see Referable 306 */ 307 public String getReferenceId() { 308 return "complexType:" + getName(); 309 } // -- getReferenceId 310 311 /** 312 * A helper method that returns true if this complexType contains an {@literal <any>} element. 313 * 314 * @return method that returns true if this complexType contains an {@literal <any>} element. 315 */ 316 public boolean hasAny() { 317 boolean result = false; 318 Enumeration<Particle> enumeration = _contentModel.enumerate(); 319 while (enumeration.hasMoreElements() && !result) { 320 Structure struct = enumeration.nextElement(); 321 switch (struct.getStructureType()) { 322 case Structure.ELEMENT: 323 break; 324 case Structure.GROUP: 325 case Structure.MODELGROUP: 326 result = ((Group) struct).hasAny(); 327 break; 328 case Structure.WILDCARD: 329 result = true; 330 break; 331 default: 332 break; 333 } 334 } 335 return result; 336 } 337 338 /** 339 * Returns true if this ComplexType has been marked as Abstract. 340 * 341 * @return true if this ComplexType is "abstract". 342 */ 343 public boolean isAbstract() { 344 return _abstract; 345 } // -- isAbstract 346 347 /** 348 * Returns true if this complexType is a redefinition. 349 * 350 * @return true if this complexType is a redefinition. 351 */ 352 public boolean isRedefined() { 353 return _redefinition; 354 } 355 356 /** 357 * Returns true if this is a top level {@link ComplexType}. 358 * 359 * @return true if this is a top level {@link ComplexType} 360 */ 361 public boolean isTopLevel() { 362 if (getName() == null) { 363 return false; 364 } 365 if (getSchema() == null) { 366 return false; 367 } 368 return (getSchema().getComplexType(getName()) == this); 369 } // -- isTopLevel 370 371 /** 372 * Returns true if this complexType is a 'complexContent'. 373 * 374 * @return true if this complexType is a 'complexContent' 375 */ 376 public boolean isComplexContent() { 377 return _complexContent; 378 } 379 380 /** 381 * Returns true if this complexType is a 'simpleContent'. 382 * 383 * @return true if this complexType is a 'simpleContent' 384 */ 385 public boolean isSimpleContent() { 386 return (!_complexContent); 387 } 388 389 /** 390 * Returns true if this complexType is a restriction. 391 * 392 * @return true if this complexType is a restriction 393 */ 394 public boolean isRestricted() { 395 return _restricted; 396 } 397 398 /** 399 * Sets whether or not this ComplexType should be abstract. 400 * 401 * @param isAbstract a boolean that when true makes this ComplexType abstract. 402 */ 403 public void setAbstract(final boolean isAbstract) { 404 _abstract = isAbstract; 405 } // -- setAbstract 406 407 /** 408 * Sets the wildcard (anyAttribute) of the {@link ComplexType}. 409 * 410 * @exception SchemaException thrown when a wildcard as already be set or when the wildCard is not 411 * an {@literal <anyAttribute>}. 412 */ 413 public void setAnyAttribute(final Wildcard wildcard) throws SchemaException { 414 if (wildcard != null) { 415 if (_anyAttribute != null) { 416 String err = "<anyAttribute> already set in this complexType: " + this.getName(); 417 throw new SchemaException(err); 418 } 419 420 if (!wildcard.isAttributeWildcard()) { 421 String err = "In complexType, " + this.getName() + "the wildcard must be an <anyAttribute>"; 422 throw new SchemaException(err); 423 } 424 } 425 _anyAttribute = wildcard; 426 } 427 428 /** 429 * Removes the given Wildcard from this Group. 430 * 431 * @param wildcard the Wildcard to remove. 432 * @return true if the wildcard has been successfully removed, false otherwise. 433 */ 434 public boolean removeWildcard(final Wildcard wildcard) { 435 if (wildcard == null) { 436 return false; 437 } 438 if (wildcard.equals(_anyAttribute)) { 439 _anyAttribute = null; 440 return true; 441 } 442 return false; 443 444 } 445 446 public void addWildcard(final Wildcard wildcard) throws SchemaException { 447 setAnyAttribute(wildcard); 448 } 449 450 /** 451 * Sets the base type that this type is derived from. 452 * 453 * @param base the type that this type is derived from 454 */ 455 public void setBase(final String base) { 456 _baseType = base; 457 } // -- setBase 458 459 /** 460 * Sets the base type for this ComplexType. 461 * 462 * @param baseType the base type which this ComplexType extends or restricts 463 */ 464 public void setBaseType(final XMLType baseType) { 465 super.setBaseType(baseType); 466 if (baseType != null) { 467 if (baseType.isSimpleType()) { 468 _complexContent = false; 469 _content = new SimpleContent((SimpleType) baseType); 470 } else if (baseType.isComplexType()) { 471 ComplexType complexType = (ComplexType) baseType; 472 if (complexType.isSimpleContent()) { 473 _complexContent = false; 474 _content = ((SimpleContent) complexType.getContentType()).copy(); 475 } else { 476 _complexContent = true; 477 } 478 } else { 479 // -- assuming anyType 480 _complexContent = true; 481 } 482 } 483 } // -- setBaseType 484 485 /** 486 * Sets the value of the 'block' attribute for this ComplexType. 487 * 488 * @param block the value of the block attribute for this ComplexType definition. 489 */ 490 public void setBlock(final BlockList block) { 491 492 if (block != null) { 493 if (block.hasSubstitution()) { 494 String err = "'substitution' is an illegal value of the " 495 + "'block' attribute for a complexType definition."; 496 throw new IllegalArgumentException(err); 497 } 498 } 499 _block = block; 500 } // -- setBlock 501 502 /** 503 * Sets the value of the 'block' attribute for this ComplexType. 504 * 505 * @param block the value of the block attribute for this ComplexType definition. 506 */ 507 public void setBlock(final String block) { 508 if (block == null) { 509 _block = null; 510 } else { 511 setBlock(new BlockList(block)); 512 } 513 } // -- setBlock 514 515 /** 516 * Sets whether or not this complexType is a 'complexContent'. 517 * 518 * @param complexContent true if this complexType is a 'complexContent' 519 */ 520 public void setComplexContent(final boolean complexContent) { 521 this._complexContent = complexContent; 522 } 523 524 /** 525 * Sets the content type of this complexType. The Content Type holds the information about the 526 * content of the complexType. For instance, if this complexType is a simpleContent then the 527 * simpleType information will be hold in the content type. 528 * 529 * @param contentType the ContentType for this complexType 530 */ 531 public void setContentType(final ContentType contentType) { 532 _content = contentType; 533 } // -- setContentType 534 535 /** 536 * Sets the value of the 'final' attribute for this ComplexType definition. 537 * 538 * @param finalList the value of the final attribute for this ComplexType definition. 539 */ 540 public void setFinal(final FinalList finalList) { 541 _final = finalList; 542 } // -- setFinal 543 544 /** 545 * Sets the value of the 'final' attribute for this ComplexType definition. 546 * 547 * @param finalValue the value of the final attribute for this ComplexType definition. 548 */ 549 public void setFinal(final String finalValue) { 550 if (finalValue == null) { 551 _final = null; 552 } else { 553 _final = new FinalList(finalValue); 554 } 555 } // -- setFinal 556 557 /** 558 * Sets this Group has redefined. 559 */ 560 public void setRedefined() { 561 _redefinition = true; 562 } 563 564 /** 565 * Sets whether or not this complexType is a 'simpleContent'. 566 * 567 * @param simpleContent true if this complexType is a 'simpleContent' 568 */ 569 public void setSimpleContent(final boolean simpleContent) { 570 _complexContent = (!simpleContent); 571 } 572 573 /** 574 * Sets whether or not this complexType is a restriction. 575 * 576 * @param restricted true if this complexType is a restriction 577 */ 578 public void setRestriction(final boolean restricted) { 579 this._restricted = restricted; 580 } 581 582 public void useResolver(final Resolver resolver) { 583 // do nothing for now 584 } 585 586 // ---------------------------------------/ 587 // - Implementation of ContentModelGroup -/ 588 // ---------------------------------------/ 589 590 /** 591 * Adds the given ElementDecl to this {@link ContentModelGroup}. 592 * 593 * @param elementDecl the ElementDecl to add 594 * @exception SchemaException when an ElementDecl already exists with the same name as the given 595 * ElementDecl 596 */ 597 public void addElementDecl(final ElementDecl elementDecl) throws SchemaException { 598 _contentModel.addElementDecl(elementDecl); 599 600 // --set the parent 601 elementDecl.setParent(this); 602 } // -- addElementDecl 603 604 /** 605 * Removes the given ElementDecl from this ContentModelGroup. 606 * 607 * @param element the ElementDecl to remove. 608 * @return true if the element has been successfully removed, false otherwise. 609 */ 610 public boolean removeElementDecl(final ElementDecl element) { 611 return _contentModel.removeElementDecl(element); 612 } 613 614 /** 615 * Adds the given Group to this {@link ContentModelGroup}. 616 * 617 * @param group the Group to add 618 * @exception SchemaException when a group with the same name as the specified group already 619 * exists in the current scope 620 */ 621 public void addGroup(final Group group) throws SchemaException { 622 _contentModel.addGroup(group); 623 624 // -- set reference to parent 625 group.setParent(this); 626 } // -- addGroup 627 628 /** 629 * Removes the given Group from this ContentModelGroup. 630 * 631 * @param group the Group to remove. 632 * @return true if the group has been successfully removed, false otherwise. 633 */ 634 public boolean removeGroup(final Group group) { 635 boolean result = _contentModel.removeGroup(group); 636 group.setParent(null); 637 return result; 638 } 639 640 /** 641 * Adds the given ModelGroup Definition to this {@link ContentModelGroup}. 642 * 643 * @param group the ModelGroup to add 644 * @exception SchemaException when a group with the same name as the specified group already 645 * exists in the current scope 646 */ 647 public void addGroup(final ModelGroup group) throws SchemaException { 648 _contentModel.addGroup(group); 649 650 // -- set reference to parent 651 group.setParent(this); 652 } // -- addGroup 653 654 /** 655 * Removes the given ModelGroup Definition from this ContentModelGroup. 656 * 657 * @param group the ModelGroup Definition to remove. 658 * @return true if the group has been successfully removed, false otherwise. 659 */ 660 public boolean removeGroup(final ModelGroup group) { 661 boolean result = _contentModel.removeGroup(group); 662 group.setParent(null); 663 return result; 664 } 665 666 /** 667 * Returns an enumeration of all the Particles of this ContentModelGroup. 668 * 669 * @return an enumeration of the Particles contained within this ContentModelGroup 670 */ 671 public Enumeration<Particle> enumerate() { 672 return _contentModel.enumerate(); 673 } // -- enumerate 674 675 /** 676 * Returns the element declaration with the given name, or null if no element declaration with 677 * that name exists in this ContentModelGroup. 678 * 679 * @param name the name of the element. 680 * @return the ElementDecl with the given name, or null if no ElementDecl exists in this 681 * ContentModelGroup. 682 */ 683 public ElementDecl getElementDecl(final String name) { 684 ElementDecl result = _contentModel.getElementDecl(name); 685 return result; 686 } // -- getElementDecl 687 688 /** 689 * Returns the maximum number of occurances that this ContentModelGroup may appear. 690 * 691 * @return the maximum number of occurances that this ContentModelGroup may appear. A non positive 692 * (n < 1) value indicates that the value is unspecified (ie. unbounded). 693 */ 694 public int getMaxOccurs() { 695 696 if (_contentModel.getParticleCount() > 0) { 697 Particle particle = _contentModel.getParticle(0); 698 if (particle instanceof ContentModelGroup) { 699 return particle.getMaxOccurs(); 700 } 701 } 702 703 return _contentModel.getMaxOccurs(); 704 } // -- getMaxOccurs 705 706 /** 707 * Returns the minimum number of occurances that this ContentModelGroup must appear. 708 * 709 * @return the minimum number of occurances that this ContentModelGroup must appear A negative (n 710 * < 0) value indicates that the value is unspecified. 711 */ 712 public int getMinOccurs() { 713 if (_contentModel.getParticleCount() > 0) { 714 Particle particle = _contentModel.getParticle(0); 715 if (particle instanceof ContentModelGroup) { 716 return particle.getMinOccurs(); 717 } 718 } 719 return _contentModel.getMinOccurs(); 720 } // -- getMinOccurs 721 722 /** 723 * Returns the Particle at the specified index 724 * 725 * @param index the index of the particle to return 726 * @return the CMParticle at the specified index 727 */ 728 public Particle getParticle(final int index) { 729 Particle result = _contentModel.getParticle(index); 730 return result; 731 } // -- getParticle 732 733 /** 734 * Returns the number of particles contained within this ContentModelGroup. 735 * 736 * @return the number of particles 737 */ 738 public int getParticleCount() { 739 return _contentModel.getParticleCount(); 740 } // -- getParticleCount 741 742 // -------------------------------/ 743 // - Implementation of Structure -/ 744 // -------------------------------/ 745 746 /** 747 * Returns the type of this Schema Structure. 748 * 749 * @return the type of this Schema Structure 750 */ 751 public short getStructureType() { 752 return Structure.COMPLEX_TYPE; 753 } // -- getStructureType 754 755 /** 756 * Checks the validity of this ComplexType defintion. 757 * 758 * @throws ValidationException when this ComplexType definition is invalid. 759 */ 760 public void validate() throws ValidationException { 761 // -- check name 762 if (_parent != null && _parent.getStructureType() != Structure.SCHEMA) { 763 if (getName() != null) { 764 String err = "Only top-level complexTypes can be named."; 765 err += getName() + "is not a valid complexType."; 766 throw new ValidationException(err); 767 } 768 } 769 // -- check attributes 770 _attributes.validate(); 771 772 // -- check content model 773 Enumeration<Particle> enumeration = _contentModel.enumerate(); 774 while (enumeration.hasMoreElements()) { 775 enumeration.nextElement().validate(); 776 } 777 778 // -- make sure baseType is accessible 779 XMLType type = getBaseType(); 780 if ((type == null) && (_baseType != null)) { 781 String error = "The base type '" + _baseType + "' was not found."; 782 throw new ValidationException(error); 783 } 784 if (type != null) { 785 if (type.getStructureType() == Structure.SIMPLE_TYPE) { 786 if (_restricted) { 787 String name = getName(); 788 if (name == null) { 789 name = "anonymous-complexType-for-element: "; 790 if (_parent != null) { 791 // -- parent should be an element if name is null, 792 // but 793 // -- we'll check the type to be on the safe side 794 if (_parent.getStructureType() == Structure.ELEMENT) { 795 name += ((ElementDecl) _parent).getName(); 796 } else { 797 name += _parent.toString(); 798 } 799 } 800 } 801 String err = "complexType: " + name; 802 err += "; A complex type cannot be a restriction" + " of a simpleType:"; 803 err += type.getName(); 804 throw new ValidationException(err); 805 } 806 } else if (type.getStructureType() == Structure.COMPLEX_TYPE) { 807 808 if (!_complexContent) { 809 // we are now sure that the base is a ComplexType 810 // but is the base of this complexType a simpleType? (see 811 // 4.3.3->simpleContent->content type) 812 if (((ComplexType) type).getContentType().getType() != ContentType.SIMPLE) { 813 String name = getName(); 814 if (name == null) { 815 name = "anonymous-complexType-for-element: "; 816 if (_parent != null) { 817 // -- parent should be an element if name is 818 // null, but 819 // -- we'll check the type to be on the safe 820 // side 821 if (_parent.getStructureType() == Structure.ELEMENT) { 822 name += ((ElementDecl) _parent).getName(); 823 } else { 824 name += _parent.toString(); 825 } 826 } 827 } 828 String err = "complexType: " + name; 829 err += "; When a complexType is a restriction of simpleContent the base type" 830 + " must be a complexType whose base is also simpleContent."; 831 throw new ValidationException(err); 832 } 833 } 834 } 835 } 836 837 } // -- validate 838 839 // ---------------------/ 840 // - Protected Methods -/ 841 // ---------------------/ 842 843 /** 844 * Sets the parent for this ComplexType. 845 * 846 * @param parent the parent Structure for this ComplexType 847 */ 848 protected void setParent(final Structure parent) { 849 if (parent != null) { 850 switch (parent.getStructureType()) { 851 case Structure.SCHEMA: 852 case Structure.ELEMENT: 853 break; 854 default: 855 String error = "Invalid parent for ComplexType"; 856 throw new IllegalArgumentException(error); 857 } 858 } 859 _parent = parent; 860 } // -- setParent 861 862 /** 863 * @return true if the content model for this ComplexType is emptiable. 864 */ 865 public boolean isEmptiable() { 866 switch (getParticleCount()) { 867 case 0: 868 return true; 869 case 1: 870 Particle p = getParticle(0); 871 if (p.isEmptiable()) { 872 if ((_baseType != null) && !isRestricted()) { 873 // derived by extension 874 XMLType baseType = getBaseType(); 875 if ((baseType != null) && baseType.isComplexType() 876 && ((ComplexType) baseType).isEmptiable()) { 877 return true; 878 } 879 } else { 880 // derived by restriction (explicit or shorthand from 881 // xs:anyType 882 return true; 883 } 884 } 885 break; 886 } 887 return false; 888 } 889 890 } // -- Complextype