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