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-2003 (C) Intalio, Inc. All Rights Reserved. 32 * 33 * $Id$ 34 */ 35 36 37 package org.exolab.castor.xml.schema; 38 39 import org.exolab.castor.xml.ValidationException; 40 41 /** 42 * An XML Schema Attribute Definition 43 * 44 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 45 * @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $ 46 **/ 47 public final class AttributeDecl extends Annotated { 48 /** SerialVersionUID */ 49 private static final long serialVersionUID = -8720345516857919305L; 50 51 /** 52 * The use attribute value for optional 53 **/ 54 public static final String USE_OPTIONAL = "optional"; 55 56 /** 57 * The use attribute value for prohibited 58 **/ 59 public static final String USE_PROHIBITED = "prohibited"; 60 61 /** 62 * The use attribute value for required 63 **/ 64 public static final String USE_REQUIRED = "required"; 65 66 67 private static final short OPTIONAL = 3; 68 private static final short PROHIBITED = 4; 69 private static final short REQUIRED = 5; 70 71 /** 72 * Error message for a null argument 73 **/ 74 private static String NULL_ARGUMENT = 75 "A null argument was passed to the constructor of " + AttributeDecl.class.getName(); 76 77 /** 78 * The default namespace form for this AttributeDecl (optional). 79 **/ 80 private Form _form = null; 81 82 /** 83 * The id for this AttributeDecl 84 **/ 85 private String _id = null; 86 87 /** 88 * The name of attributes defined by this AttributeDecl 89 **/ 90 private String _name = null; 91 92 /** 93 * The parent for this AttributeDecl 94 **/ 95 private Structure _parent = null; 96 97 /** 98 * The Schema to which this AttributeDecl belongs 99 **/ 100 private Schema _schema = null; 101 102 /** 103 * The simple type for this AttributeDecl. 104 **/ 105 private SimpleType _simpleType = null; 106 107 108 /** 109 * The current value of the 'use' property. The value is OPTIONAL by default. 110 **/ 111 private short _useFlag = OPTIONAL; 112 113 /** 114 * The fixed value for attribute instances of this attribute declaration. 115 **/ 116 private String _fixed = null; 117 118 /** 119 * The default value for attribute instances of this attribute declaration. 120 */ 121 private String _default = null; 122 123 /** 124 * A reference to a top-level attribute 125 */ 126 private String _attributeRef = null; 127 128 /** 129 * Creates a new AttrDecl with the given name 130 * 131 * @param name of the Attribute defined by this attribute declaration 132 * @param schema the schema that contains the new attrDecl 133 **/ 134 public AttributeDecl(Schema schema, String name) { 135 136 if (schema == null) { 137 String err = NULL_ARGUMENT + "; 'schema' must not be null."; 138 throw new IllegalArgumentException(err); 139 } 140 _schema = schema; 141 setName(name); 142 } // -- AttributeDecl 143 144 /** 145 * Creates a new AttrDecl in the given schema. 146 * 147 * @param schema the schema that contains the new attrDecl 148 **/ 149 public AttributeDecl(Schema schema) { 150 151 if (schema == null) { 152 String err = NULL_ARGUMENT + "; 'schema' must not be null."; 153 throw new IllegalArgumentException(err); 154 } 155 _schema = schema; 156 } // -- AttributeDecl 157 158 159 /** 160 * Returns the Form for this attribute declaration. The Form object species whether or not names 161 * are qualified or unqualified for instances of this attribute declaration. If null, the Form 162 * should be obtained from the parent Schema. 163 * 164 * @return the Form for this attribute declaration, or null if not set. 165 **/ 166 public Form getForm() { 167 return _form; 168 } // -- getForm 169 170 /** 171 * Returns the Id for this attribute declaration 172 * 173 * @return the Id for this attribute declaration 174 **/ 175 public String getId() { 176 return _id; 177 } // -- getId 178 179 /** 180 * Returns the name of attributes defined by this AttributeDecl. If this AttributeDecl is a 181 * reference to another AttributeDecl, the reference will be resolved and the name of the 182 * referenced AttributeDecl will be returned. The name will always be an NCName, no namespace 183 * prefix will be included. 184 * 185 * @return the name of attributes defined by this AttributeDecl. 186 **/ 187 public String getName() { 188 return getName(false); 189 } // -- getName 190 191 /** 192 * Returns the name of this Attribute declaration. The name will always be an NCName, no namespace 193 * prefix will be included. 194 * 195 * @param ignoreRef a boolean that when false, indicates that if this is an attribute reference to 196 * return the reference name. Otherwise the only the local name is used. 197 * 198 * @return the name of this attribute declaration 199 **/ 200 public String getName(boolean ignoreRef) { 201 if (isReference() && ignoreRef == false) { 202 // -- strip prefix we can only return 203 // -- an NCName from this method 204 String ncname = _attributeRef; 205 // -- check for namespace prefix 206 int idx = ncname.indexOf(':'); 207 if (idx > 0) { 208 ncname = ncname.substring(idx + 1); 209 } 210 return ncname; 211 } 212 return _name; 213 } // -- getName 214 215 /** 216 * Returns the parent of this AttributeDecl, this value may be null if no parent has been set. 217 * 218 * @return the parent Structure of this AttributeDecl. 219 **/ 220 public Structure getParent() { 221 return _parent; 222 } // -- getParent 223 224 /** 225 * Returns the data type associated with this AttributeDecl. 226 * 227 * @return the data type associated with this AttributeDecl. 228 **/ 229 public SimpleType getSimpleType() { 230 SimpleType result = null; 231 232 if (isReference()) { 233 AttributeDecl attribute = getReference(); 234 if (attribute != null) 235 result = attribute.getSimpleType(); 236 else 237 return null; 238 } 239 240 if (_simpleType == null) 241 return null; 242 result = (SimpleType) _simpleType.getType(); 243 244 if (result != null) { 245 Schema tempSchema = result.getSchema().getMasterSchema(); 246 if (tempSchema != null) { 247 SimpleType tempType = tempSchema.getSimpleType(result.getName()); 248 if (tempType != null) { 249 result = tempType; 250 } 251 } 252 } 253 return result; 254 } // -- getSimpleType 255 256 /** 257 * Returns the AttributeDecl that this attribute definition references. This will return null if 258 * this attribute definition does not reference a different attribute definition. 259 * 260 * @return the AttributeDecl that this attribute definition references 261 **/ 262 public AttributeDecl getReference() { 263 AttributeDecl result = null; 264 if (_attributeRef != null) { 265 result = _schema.getAttribute(_attributeRef); 266 if (result == null) { 267 String err = "Unable to find attribute referenced :\" "; 268 err += _attributeRef; 269 err += "\""; 270 throw new IllegalStateException(err); 271 } 272 } 273 return result; 274 } // -- getReference 275 276 /** 277 * Returns the actual reference name of this AttributeDecl, or null if this AttributeDecl is not a 278 * reference. The name returned, if not null, will be a QName, possibly containing the namespace 279 * prefix. 280 * 281 * @return the reference name 282 */ 283 public String getReferenceName() { 284 return _attributeRef; 285 } // -- getReference 286 287 /** 288 * Returns the Schema that this AttributeGroupDecl belongs to. 289 * 290 * @return the Schema that this AttributeGroupDecl belongs to. 291 **/ 292 public Schema getSchema() { 293 return _schema; 294 } // -- getSchema 295 296 /** 297 * Returns the value of the use attribute for this attribute declaration or attribute reference. 298 * If this is a reference the value of the use attribute will *not* be obtained from the 299 * referenced attribute declaration as top-level attributes do not take into account the use 300 * attribute. 301 * 302 * @return the value of the use attribute for this attribute declaration 303 */ 304 public String getUse() { 305 306 // -- Note: Do not resolve reference, since top-level 307 // -- atts do not specify the "use" attribute. 308 309 switch (_useFlag) { 310 case PROHIBITED: 311 return USE_PROHIBITED; 312 case REQUIRED: 313 return USE_REQUIRED; 314 default: 315 return USE_OPTIONAL; 316 } 317 318 } // -- getUse 319 320 /** 321 * Returns the default value of this element definition. 322 * 323 * @return the default value of this element definition, or null if no default was specified. 324 **/ 325 public String getDefaultValue() { 326 return _default; 327 } // -- getDefaultValue 328 329 /** 330 * Returns the fixed value of this element definition. 331 * 332 * @return the fixed value of this element definition, or null if no default was specified. 333 */ 334 public String getFixedValue() { 335 return _fixed; 336 } // -- getFixedValue 337 338 /** 339 * Returns true if the "default" flag is set. 340 * 341 * @return true if the "default" flag is set. 342 */ 343 public boolean isDefault() { 344 return (_default != null) && (_default.length() > 0); 345 } // -- isFixed 346 347 348 /** 349 * Returns true if the use attribute is equal to "optional". 350 * 351 * @return true if the use attribute is equal to "optional". 352 **/ 353 public boolean isFixed() { 354 return (_fixed != null) && (_fixed.length() > 0); 355 } // -- isFixed 356 357 /** 358 * Returns true if the use attribute is equal to "optional". 359 * 360 * @return true if the use attribute is equal to "optional". 361 **/ 362 public boolean isOptional() { 363 String use = getUse(); 364 return use.equals(USE_OPTIONAL); 365 } // -- isOptional 366 367 /** 368 * Returns true if the use attribute is equal to "prohibited". 369 * 370 * @return true if the use attribute is equal to "prohibited". 371 **/ 372 public boolean isProhibited() { 373 String use = getUse(); 374 return use.equals(USE_PROHIBITED); 375 } // -- isProhibited 376 377 /** 378 * Returns true if the 'use' attribute is equal to REQUIRED and there is no specified value. If a 379 * value is specifed and the 'use' attribute is "required" then required is will return false, 380 * because the attribute value automatically becomes fixed. 381 * 382 * @return true if the use attribute is equal to "required" and no default value has been 383 * specified, otherwise false 384 **/ 385 public boolean isRequired() { 386 String use = getUse(); 387 return (use.equals(USE_REQUIRED)); 388 } // -- getRequired 389 390 /** 391 * Returns true if this attribute definition simply references another attribute Definition 392 * 393 * @return true if this attribute definition is a reference 394 */ 395 public boolean isReference() { 396 return (_attributeRef != null); 397 } // -- isReference 398 399 /** 400 * Sets the Form for this attribute declaration. The Form object species whether or not names are 401 * qualified or unqualified for instances of this attribute declaration. If null, the Form is to 402 * be obtained from the parent Schema. 403 * 404 * @param form the Form type for this attribute declaration. 405 **/ 406 public void setForm(Form form) { 407 _form = form; 408 } // -- setForm 409 410 /** 411 * Sets the Id for this attribute declaration 412 * 413 * @param id the Id for this attribute declaration 414 **/ 415 public void setId(String id) { 416 _id = id; 417 } // -- setId 418 419 /** 420 * Sets the name of attributes defined by this attribute definition 421 * 422 * @param name the name of the this AttributeDecl. Must be a valid NCName. 423 * @exception IllegalArgumentException when the name is not valid 424 **/ 425 public void setName(String name) { 426 if (name == null) { 427 String err = "AttributeDecl#setName: 'name' must not be null."; 428 throw new IllegalArgumentException(err); 429 } 430 431 // -- handle namespace if necessary 432 int idx = name.indexOf(':'); 433 if (idx >= 0) { 434 // -- we should resolve nsPrefix...just ignore for now 435 // -- use local name 436 name = name.substring(idx + 1); 437 } 438 439 if (name.length() == 0) { 440 String err = "AttributeDecl#setName: 'name' must not be " + "zero-length."; 441 throw new IllegalArgumentException(err); 442 } 443 444 _name = name; 445 } // -- setName 446 447 /** 448 * Sets the parent for this AttributeDecl 449 * 450 * @param parent the parent Structure for this AttributeDecl 451 **/ 452 protected void setParent(Structure parent) { 453 if (parent != null) { 454 switch (parent.getStructureType()) { 455 case Structure.ATTRIBUTE_GROUP: 456 case Structure.COMPLEX_TYPE: 457 case Structure.SCHEMA: 458 break; 459 default: 460 String error = "Invalid parent for group"; 461 throw new IllegalArgumentException(error); 462 } 463 } 464 _parent = parent; 465 } // -- setParent 466 467 /** 468 * Sets the reference for this attribute definition 469 * 470 * @param reference the Attribute definition that this definition references 471 **/ 472 public void setReference(AttributeDecl reference) { 473 if (reference == null) 474 this._attributeRef = null; 475 else 476 this._attributeRef = reference.getName(); 477 } // -- setReference 478 479 /** 480 * Sets the reference for this attribute definition 481 * 482 * @param reference the name of the attribute definition that this definition references 483 **/ 484 public void setReference(String reference) { 485 this._attributeRef = reference; 486 } // -- setReference 487 488 /** 489 * Sets the SimpleType for this attribute declaration 490 * 491 * @param simpleType the SimpleType for this attribute declaration 492 **/ 493 public void setSimpleType(SimpleType simpleType) { 494 _simpleType = simpleType; 495 if (simpleType != null) { 496 simpleType.setParent(this); 497 } 498 } // -- setSimpleType 499 500 /** 501 * Sets the simple type of this attribute to be a reference. 502 * 503 * @param name the name of the simpleType being referenced, must not be null. 504 **/ 505 public void setSimpleTypeReference(String name) { 506 SimpleTypeReference reference = new SimpleTypeReference(_schema, name); 507 setSimpleType(reference); 508 } // -- setSimpleTypeReference 509 510 511 /** 512 * Sets the 'use' attribute of this attribute declaration Note: this should not be used to set the 513 * flag to FIXED or DEFAULT 514 * 515 * @param value one of the following: ("prohibited" | "optional" | "required") 516 * 517 * @see #USE_PROHIBITED 518 * @see #USE_OPTIONAL 519 * @see #USE_REQUIRED 520 **/ 521 public void setUse(String value) { 522 523 if (value == null) { 524 _useFlag = OPTIONAL; 525 return; 526 } 527 528 if (value.equals(USE_REQUIRED)) 529 _useFlag = REQUIRED; 530 else if (value.equals(USE_OPTIONAL)) 531 _useFlag = OPTIONAL; 532 else if (value.equals(USE_PROHIBITED)) 533 _useFlag = PROHIBITED; 534 else { 535 throw new IllegalArgumentException("Invalid value for 'use': " + value); 536 } 537 } // -- setUse 538 539 /** 540 * Sets the DEFAULT value 541 */ 542 public void setDefaultValue(String value) { 543 if ((_fixed != null) && (_fixed.length() > 0)) { 544 throw new IllegalStateException("'default' and 'fixed' must not be both present."); 545 } 546 _default = value; 547 } 548 549 /** 550 * Sets the FIXED value. 551 */ 552 public void setFixedValue(String value) { 553 if ((_default != null) && (_default.length() > 0)) { 554 throw new IllegalStateException("'default' and 'fixed' must not be both present."); 555 } 556 _fixed = value; 557 } 558 559 // -------------------------------/ 560 // - Implementation of Structure -/ 561 // -------------------------------/ 562 563 /** 564 * Returns the type of this Schema Structure 565 * 566 * @return the type of this Schema Structure 567 **/ 568 public short getStructureType() { 569 return Structure.ATTRIBUTE; 570 } // -- getStructureType 571 572 /** 573 * Checks the validity of this Attribute declaration 574 * 575 * @exception ValidationException when this Attribute declaration is invalid 576 **/ 577 public void validate() throws ValidationException { 578 if ((_attributeRef == null) && (_name == null)) { 579 String err = "<attribute> is missing required 'name' attribute."; 580 throw new ValidationException(err); 581 } 582 583 if (_attributeRef != null) { 584 if (_schema.getAttribute(_attributeRef) == null) { 585 String err = "<attribute ref=\"" + _attributeRef + "\"> " + "is not resolvable."; 586 throw new ValidationException(err); 587 } 588 return; 589 } 590 591 } // -- validate 592 593 /** 594 * Set the parent schema of the current ElementDecl. The parent schema should at least have the 595 * same targetNamespace of the current schema. 596 * 597 * This method is protected since it is only meant to be used by the internal API to propagate the 598 * parent XML Schema in case of a redefinition for instance. 599 * 600 * @param schema 601 */ 602 protected void setSchema(Schema schema) { 603 _schema = schema; 604 } 605 606 /** 607 * Indicates whether a type is set for this element definiion. 608 * 609 * @return True if a type is set. 610 */ 611 public boolean hasXMLType() { 612 return (_simpleType != null); 613 } 614 615 } // -- AttrDecl