1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: XSLTElementDef.java 468640 2006-10-28 06:53:53Z minchau $ 20 */ 21 package org.apache.xalan.processor; 22 23 import java.util.Enumeration; 24 import java.util.Hashtable; 25 26 import org.apache.xalan.templates.Constants; 27 import org.apache.xml.utils.QName; 28 29 /** 30 * This class defines the allowed structure for an element in a XSLT stylesheet, 31 * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the 32 * mapping between Xalan classes and the markup elements in the XSLT instance. 33 * This actually represents both text nodes and elements. 34 */ 35 public class XSLTElementDef 36 { 37 38 /** 39 * Construct an instance of XSLTElementDef. This must be followed by a 40 * call to build(). 41 */ 42 XSLTElementDef(){} 43 44 /** 45 * Construct an instance of XSLTElementDef. 46 * 47 * @param namespace The Namespace URI, "*", or null. 48 * @param name The local name (without prefix), "*", or null. 49 * @param nameAlias A potential alias for the name, or null. 50 * @param elements An array of allowed child element defs, or null. 51 * @param attributes An array of allowed attribute defs, or null. 52 * @param contentHandler The element processor for this element. 53 * @param classObject The class of the object that this element def should produce. 54 */ 55 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 56 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 57 XSLTElementProcessor contentHandler, Class classObject) 58 { 59 build(namespace, name, nameAlias, elements, attributes, contentHandler, 60 classObject); 61 if ( (null != namespace) 62 && (namespace.equals(Constants.S_XSLNAMESPACEURL) 63 || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL) 64 || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL))) 65 { 66 schema.addAvailableElement(new QName(namespace, name)); 67 if(null != nameAlias) 68 schema.addAvailableElement(new QName(namespace, nameAlias)); 69 } 70 } 71 72 /** 73 * Construct an instance of XSLTElementDef. 74 * 75 * @param namespace The Namespace URI, "*", or null. 76 * @param name The local name (without prefix), "*", or null. 77 * @param nameAlias A potential alias for the name, or null. 78 * @param elements An array of allowed child element defs, or null. 79 * @param attributes An array of allowed attribute defs, or null. 80 * @param contentHandler The element processor for this element. 81 * @param classObject The class of the object that this element def should produce. 82 * @param has_required true if this element has required elements by the XSLT specification. 83 */ 84 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 85 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 86 XSLTElementProcessor contentHandler, Class classObject, boolean has_required) 87 { 88 this.m_has_required = has_required; 89 build(namespace, name, nameAlias, elements, attributes, contentHandler, 90 classObject); 91 if ( (null != namespace) 92 && (namespace.equals(Constants.S_XSLNAMESPACEURL) 93 || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL) 94 || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL))) 95 { 96 schema.addAvailableElement(new QName(namespace, name)); 97 if(null != nameAlias) 98 schema.addAvailableElement(new QName(namespace, nameAlias)); 99 } 100 101 } 102 103 /** 104 * Construct an instance of XSLTElementDef. 105 * 106 * @param namespace The Namespace URI, "*", or null. 107 * @param name The local name (without prefix), "*", or null. 108 * @param nameAlias A potential alias for the name, or null. 109 * @param elements An array of allowed child element defs, or null. 110 * @param attributes An array of allowed attribute defs, or null. 111 * @param contentHandler The element processor for this element. 112 * @param classObject The class of the object that this element def should produce. 113 * @param has_required true if this element has required elements by the XSLT specification. 114 * @param required true if this element is required by the XSLT specification. 115 */ 116 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 117 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 118 XSLTElementProcessor contentHandler, Class classObject, 119 boolean has_required, boolean required) 120 { 121 this(schema, namespace, name, nameAlias, 122 elements, attributes, 123 contentHandler, classObject, has_required); 124 this.m_required = required; 125 } 126 127 /** 128 * Construct an instance of XSLTElementDef. 129 * 130 * @param namespace The Namespace URI, "*", or null. 131 * @param name The local name (without prefix), "*", or null. 132 * @param nameAlias A potential alias for the name, or null. 133 * @param elements An array of allowed child element defs, or null. 134 * @param attributes An array of allowed attribute defs, or null. 135 * @param contentHandler The element processor for this element. 136 * @param classObject The class of the object that this element def should produce. 137 * @param has_required true if this element has required elements by the XSLT specification. 138 * @param required true if this element is required by the XSLT specification. 139 * @param order the order this element should appear according to the XSLT specification. 140 * @param multiAllowed whether this element is allowed more than once 141 */ 142 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 143 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 144 XSLTElementProcessor contentHandler, Class classObject, 145 boolean has_required, boolean required, int order, 146 boolean multiAllowed) 147 { 148 this(schema, namespace, name, nameAlias, 149 elements, attributes, 150 contentHandler, classObject, has_required, required); 151 this.m_order = order; 152 this.m_multiAllowed = multiAllowed; 153 } 154 155 /** 156 * Construct an instance of XSLTElementDef. 157 * 158 * @param namespace The Namespace URI, "*", or null. 159 * @param name The local name (without prefix), "*", or null. 160 * @param nameAlias A potential alias for the name, or null. 161 * @param elements An array of allowed child element defs, or null. 162 * @param attributes An array of allowed attribute defs, or null. 163 * @param contentHandler The element processor for this element. 164 * @param classObject The class of the object that this element def should produce. 165 * @param has_required true if this element has required elements by the XSLT specification. 166 * @param required true if this element is required by the XSLT specification. 167 * @param has_order whether this element has ordered child elements 168 * @param order the order this element should appear according to the XSLT specification. 169 * @param multiAllowed whether this element is allowed more than once 170 */ 171 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 172 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 173 XSLTElementProcessor contentHandler, Class classObject, 174 boolean has_required, boolean required, boolean has_order, int order, 175 boolean multiAllowed) 176 { 177 this(schema, namespace, name, nameAlias, 178 elements, attributes, 179 contentHandler, classObject, has_required, required); 180 this.m_order = order; 181 this.m_multiAllowed = multiAllowed; 182 this.m_isOrdered = has_order; 183 } 184 185 /** 186 * Construct an instance of XSLTElementDef. 187 * 188 * @param namespace The Namespace URI, "*", or null. 189 * @param name The local name (without prefix), "*", or null. 190 * @param nameAlias A potential alias for the name, or null. 191 * @param elements An array of allowed child element defs, or null. 192 * @param attributes An array of allowed attribute defs, or null. 193 * @param contentHandler The element processor for this element. 194 * @param classObject The class of the object that this element def should produce. 195 * @param has_order whether this element has ordered child elements 196 * @param order the order this element should appear according to the XSLT specification. 197 * @param multiAllowed whether this element is allowed more than once 198 */ 199 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 200 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 201 XSLTElementProcessor contentHandler, Class classObject, 202 boolean has_order, int order, boolean multiAllowed) 203 { 204 this(schema, namespace, name, nameAlias, 205 elements, attributes, 206 contentHandler, classObject, 207 order, multiAllowed); 208 this.m_isOrdered = has_order; 209 } 210 211 /** 212 * Construct an instance of XSLTElementDef. 213 * 214 * @param namespace The Namespace URI, "*", or null. 215 * @param name The local name (without prefix), "*", or null. 216 * @param nameAlias A potential alias for the name, or null. 217 * @param elements An array of allowed child element defs, or null. 218 * @param attributes An array of allowed attribute defs, or null. 219 * @param contentHandler The element processor for this element. 220 * @param classObject The class of the object that this element def should produce. 221 * @param order the order this element should appear according to the XSLT specification. 222 * @param multiAllowed whether this element is allowed more than once 223 */ 224 XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, 225 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 226 XSLTElementProcessor contentHandler, Class classObject, 227 int order, boolean multiAllowed) 228 { 229 this(schema, namespace, name, nameAlias, elements, attributes, contentHandler, 230 classObject); 231 this.m_order = order; 232 this.m_multiAllowed = multiAllowed; 233 } 234 235 /** 236 * Construct an instance of XSLTElementDef that represents text. 237 * 238 * @param classObject The class of the object that this element def should produce. 239 * @param contentHandler The element processor for this element. 240 * @param type Content type, one of T_ELEMENT, T_PCDATA, or T_ANY. 241 */ 242 XSLTElementDef(Class classObject, XSLTElementProcessor contentHandler, 243 int type) 244 { 245 246 this.m_classObject = classObject; 247 this.m_type = type; 248 249 setElementProcessor(contentHandler); 250 } 251 252 /** 253 * Construct an instance of XSLTElementDef. 254 * 255 * @param namespace The Namespace URI, "*", or null. 256 * @param name The local name (without prefix), "*", or null. 257 * @param nameAlias A potential alias for the name, or null. 258 * @param elements An array of allowed child element defs, or null. 259 * @param attributes An array of allowed attribute defs, or null. 260 * @param contentHandler The element processor for this element. 261 * @param classObject The class of the object that this element def should produce. 262 */ 263 void build(String namespace, String name, String nameAlias, 264 XSLTElementDef[] elements, XSLTAttributeDef[] attributes, 265 XSLTElementProcessor contentHandler, Class classObject) 266 { 267 268 this.m_namespace = namespace; 269 this.m_name = name; 270 this.m_nameAlias = nameAlias; 271 this.m_elements = elements; 272 this.m_attributes = attributes; 273 274 setElementProcessor(contentHandler); 275 276 this.m_classObject = classObject; 277 278 if (hasRequired() && m_elements != null) 279 { 280 int n = m_elements.length; 281 for (int i = 0; i < n; i++) 282 { 283 XSLTElementDef def = m_elements[i]; 284 285 if (def != null && def.getRequired()) 286 { 287 if (m_requiredFound == null) 288 m_requiredFound = new Hashtable(); 289 m_requiredFound.put(def.getName(), "xsl:" +def.getName()); 290 } 291 } 292 } 293 } 294 295 /** 296 * Tell if two objects are equal, when either one may be null. 297 * If both are null, they are considered equal. 298 * 299 * @param obj1 A reference to the first object, or null. 300 * @param obj2 A reference to the second object, or null. 301 * 302 * @return true if the to objects are equal by both being null or 303 * because obj2.equals(obj1) returns true. 304 */ 305 private static boolean equalsMayBeNull(Object obj1, Object obj2) 306 { 307 return (obj2 == obj1) 308 || ((null != obj1) && (null != obj2) && obj2.equals(obj1)); 309 } 310 311 /** 312 * Tell if the two string refs are equal, 313 * equality being defined as: 314 * 1) Both strings are null. 315 * 2) One string is null and the other is empty. 316 * 3) Both strings are non-null, and equal. 317 * 318 * @param s1 A reference to the first string, or null. 319 * @param s2 A reference to the second string, or null. 320 * 321 * @return true if Both strings are null, or if 322 * one string is null and the other is empty, or if 323 * both strings are non-null, and equal because 324 * s1.equals(s2) returns true. 325 */ 326 private static boolean equalsMayBeNullOrZeroLen(String s1, String s2) 327 { 328 329 int len1 = (s1 == null) ? 0 : s1.length(); 330 int len2 = (s2 == null) ? 0 : s2.length(); 331 332 return (len1 != len2) ? false 333 : (len1 == 0) ? true 334 : s1.equals(s2); 335 } 336 337 /** Content type enumerations */ 338 static final int T_ELEMENT = 1, T_PCDATA = 2, T_ANY = 3; 339 340 /** 341 * The type of this element. 342 */ 343 private int m_type = T_ELEMENT; 344 345 /** 346 * Get the type of this element. 347 * 348 * @return Content type, one of T_ELEMENT, T_PCDATA, or T_ANY. 349 */ 350 int getType() 351 { 352 return m_type; 353 } 354 355 /** 356 * Set the type of this element. 357 * 358 * @param t Content type, one of T_ELEMENT, T_PCDATA, or T_ANY. 359 */ 360 void setType(int t) 361 { 362 m_type = t; 363 } 364 365 /** 366 * The allowed namespace for this element. 367 */ 368 private String m_namespace; 369 370 /** 371 * Get the allowed namespace for this element. 372 * 373 * @return The Namespace URI, "*", or null. 374 */ 375 String getNamespace() 376 { 377 return m_namespace; 378 } 379 380 /** 381 * The name of this element. 382 */ 383 private String m_name; 384 385 /** 386 * Get the local name of this element. 387 * 388 * @return The local name of this element, "*", or null. 389 */ 390 String getName() 391 { 392 return m_name; 393 } 394 395 /** 396 * The name of this element. 397 */ 398 private String m_nameAlias; 399 400 /** 401 * Get the name of this element. 402 * 403 * @return A potential alias for the name, or null. 404 */ 405 String getNameAlias() 406 { 407 return m_nameAlias; 408 } 409 410 /** 411 * The allowed elements for this type. 412 */ 413 private XSLTElementDef[] m_elements; 414 415 /** 416 * Get the allowed elements for this type. 417 * 418 * @return An array of allowed child element defs, or null. 419 * @xsl.usage internal 420 */ 421 public XSLTElementDef[] getElements() 422 { 423 return m_elements; 424 } 425 426 /** 427 * Set the allowed elements for this type. 428 * 429 * @param defs An array of allowed child element defs, or null. 430 */ 431 void setElements(XSLTElementDef[] defs) 432 { 433 m_elements = defs; 434 } 435 436 /** 437 * Tell if the namespace URI and local name match this 438 * element. 439 * @param uri The namespace uri, which may be null. 440 * @param localName The local name of an element, which may be null. 441 * 442 * @return true if the uri and local name arguments are considered 443 * to match the uri and local name of this element def. 444 */ 445 private boolean QNameEquals(String uri, String localName) 446 { 447 448 return (equalsMayBeNullOrZeroLen(m_namespace, uri) 449 && (equalsMayBeNullOrZeroLen(m_name, localName) 450 || equalsMayBeNullOrZeroLen(m_nameAlias, localName))); 451 } 452 453 /** 454 * Given a namespace URI, and a local name, get the processor 455 * for the element, or return null if not allowed. 456 * 457 * @param uri The Namespace URI, or an empty string. 458 * @param localName The local name (without prefix), or empty string if not namespace processing. 459 * 460 * @return The element processor that matches the arguments, or null. 461 */ 462 XSLTElementProcessor getProcessorFor(String uri, String localName) 463 { 464 465 XSLTElementProcessor elemDef = null; // return value 466 467 if (null == m_elements) 468 return null; 469 470 int n = m_elements.length; 471 int order = -1; 472 boolean multiAllowed = true; 473 for (int i = 0; i < n; i++) 474 { 475 XSLTElementDef def = m_elements[i]; 476 477 // A "*" signals that the element allows literal result 478 // elements, so just assign the def, and continue to 479 // see if anything else matches. 480 if (def.m_name.equals("*")) 481 { 482 483 // Don't allow xsl elements 484 if (!equalsMayBeNullOrZeroLen(uri, Constants.S_XSLNAMESPACEURL)) 485 { 486 elemDef = def.m_elementProcessor; 487 order = def.getOrder(); 488 multiAllowed = def.getMultiAllowed(); 489 } 490 } 491 else if (def.QNameEquals(uri, localName)) 492 { 493 if (def.getRequired()) 494 this.setRequiredFound(def.getName(), true); 495 order = def.getOrder(); 496 multiAllowed = def.getMultiAllowed(); 497 elemDef = def.m_elementProcessor; 498 break; 499 } 500 } 501 502 if (elemDef != null && this.isOrdered()) 503 { 504 int lastOrder = getLastOrder(); 505 if (order > lastOrder) 506 setLastOrder(order); 507 else if (order == lastOrder && !multiAllowed) 508 { 509 return null; 510 } 511 else if (order < lastOrder && order > 0) 512 { 513 return null; 514 } 515 } 516 517 return elemDef; 518 } 519 520 /** 521 * Given an unknown element, get the processor 522 * for the element. 523 * 524 * @param uri The Namespace URI, or an empty string. 525 * @param localName The local name (without prefix), or empty string if not namespace processing. 526 * 527 * @return normally a {@link ProcessorUnknown} reference. 528 * @see ProcessorUnknown 529 */ 530 XSLTElementProcessor getProcessorForUnknown(String uri, String localName) 531 { 532 533 // XSLTElementProcessor lreDef = null; // return value 534 if (null == m_elements) 535 return null; 536 537 int n = m_elements.length; 538 539 for (int i = 0; i < n; i++) 540 { 541 XSLTElementDef def = m_elements[i]; 542 543 if (def.m_name.equals("unknown") && uri.length() > 0) 544 { 545 return def.m_elementProcessor; 546 } 547 } 548 549 return null; 550 } 551 552 /** 553 * The allowed attributes for this type. 554 */ 555 private XSLTAttributeDef[] m_attributes; 556 557 /** 558 * Get the allowed attributes for this type. 559 * 560 * @return An array of allowed attribute defs, or null. 561 */ 562 XSLTAttributeDef[] getAttributes() 563 { 564 return m_attributes; 565 } 566 567 /** 568 * Given a namespace URI, and a local name, return the element's 569 * attribute definition, if it has one. 570 * 571 * @param uri The Namespace URI, or an empty string. 572 * @param localName The local name (without prefix), or empty string if not namespace processing. 573 * 574 * @return The attribute def that matches the arguments, or null. 575 */ 576 XSLTAttributeDef getAttributeDef(String uri, String localName) 577 { 578 579 XSLTAttributeDef defaultDef = null; 580 XSLTAttributeDef[] attrDefs = getAttributes(); 581 int nAttrDefs = attrDefs.length; 582 583 for (int k = 0; k < nAttrDefs; k++) 584 { 585 XSLTAttributeDef attrDef = attrDefs[k]; 586 String uriDef = attrDef.getNamespace(); 587 String nameDef = attrDef.getName(); 588 589 if (nameDef.equals("*") && (equalsMayBeNullOrZeroLen(uri, uriDef) || 590 (uriDef != null && uriDef.equals("*") && uri!=null && uri.length() > 0 ))) 591 { 592 return attrDef; 593 } 594 else if (nameDef.equals("*") && (uriDef == null)) 595 { 596 597 // In this case, all attributes are legal, so return 598 // this as the last resort. 599 defaultDef = attrDef; 600 } 601 else if (equalsMayBeNullOrZeroLen(uri, uriDef) 602 && localName.equals(nameDef)) 603 { 604 return attrDef; 605 } 606 } 607 608 if (null == defaultDef) 609 { 610 if (uri.length() > 0 && !equalsMayBeNullOrZeroLen(uri, Constants.S_XSLNAMESPACEURL)) 611 { 612 return XSLTAttributeDef.m_foreignAttr; 613 } 614 } 615 616 return defaultDef; 617 } 618 619 /** 620 * If non-null, the ContentHandler/TransformerFactory for this element. 621 */ 622 private XSLTElementProcessor m_elementProcessor; 623 624 /** 625 * Return the XSLTElementProcessor for this element. 626 * 627 * @return The element processor for this element. 628 * @xsl.usage internal 629 */ 630 public XSLTElementProcessor getElementProcessor() 631 { 632 return m_elementProcessor; 633 } 634 635 /** 636 * Set the XSLTElementProcessor for this element. 637 * 638 * @param handler The element processor for this element. 639 * @xsl.usage internal 640 */ 641 public void setElementProcessor(XSLTElementProcessor handler) 642 { 643 644 if (handler != null) 645 { 646 m_elementProcessor = handler; 647 648 m_elementProcessor.setElemDef(this); 649 } 650 } 651 652 /** 653 * If non-null, the class object that should in instantiated for 654 * a Xalan instance of this element. 655 */ 656 private Class m_classObject; 657 658 /** 659 * Return the class object that should in instantiated for 660 * a Xalan instance of this element. 661 * 662 * @return The class of the object that this element def should produce, or null. 663 */ 664 Class getClassObject() 665 { 666 return m_classObject; 667 } 668 669 /** 670 * If true, this has a required element. 671 */ 672 private boolean m_has_required = false; 673 674 /** 675 * Get whether or not this has a required element. 676 * 677 * @return true if this this has a required element. 678 */ 679 boolean hasRequired() 680 { 681 return m_has_required; 682 } 683 684 /** 685 * If true, this is a required element. 686 */ 687 private boolean m_required = false; 688 689 /** 690 * Get whether or not this is a required element. 691 * 692 * @return true if this is a required element. 693 */ 694 boolean getRequired() 695 { 696 return m_required; 697 } 698 699 Hashtable m_requiredFound; 700 701 /** 702 * Set this required element found. 703 * 704 */ 705 void setRequiredFound(String elem, boolean found) 706 { 707 if (m_requiredFound.get(elem) != null) 708 m_requiredFound.remove(elem); 709 } 710 711 /** 712 * Get whether all required elements were found. 713 * 714 * @return true if all required elements were found. 715 */ 716 boolean getRequiredFound() 717 { 718 if (m_requiredFound == null) 719 return true; 720 return m_requiredFound.isEmpty(); 721 } 722 723 /** 724 * Get required elements that were not found. 725 * 726 * @return required elements that were not found. 727 */ 728 String getRequiredElem() 729 { 730 if (m_requiredFound == null) 731 return null; 732 Enumeration elems = m_requiredFound.elements(); 733 String s = ""; 734 boolean first = true; 735 while (elems.hasMoreElements()) 736 { 737 if (first) 738 first = false; 739 else 740 s = s + ", "; 741 s = s + (String)elems.nextElement(); 742 } 743 return s; 744 } 745 746 boolean m_isOrdered = false; 747 748 /** 749 * Get whether this element requires ordered children. 750 * 751 * @return true if this element requires ordered children. 752 */ 753 boolean isOrdered() 754 { 755 /*if (!m_CheckedOrdered) 756 { 757 m_CheckedOrdered = true; 758 m_isOrdered = false; 759 if (null == m_elements) 760 return false; 761 762 int n = m_elements.length; 763 764 for (int i = 0; i < n; i++) 765 { 766 if (m_elements[i].getOrder() > 0) 767 { 768 m_isOrdered = true; 769 return true; 770 } 771 } 772 return false; 773 } 774 else*/ 775 return m_isOrdered; 776 } 777 778 /** 779 * the order that this element should appear, or -1 if not ordered 780 */ 781 private int m_order = -1; 782 783 /** 784 * Get the order that this element should appear . 785 * 786 * @return the order that this element should appear. 787 */ 788 int getOrder() 789 { 790 return m_order; 791 } 792 793 /** 794 * the highest order of child elements have appeared so far, 795 * or -1 if not ordered 796 */ 797 private int m_lastOrder = -1; 798 799 /** 800 * Get the highest order of child elements have appeared so far . 801 * 802 * @return the highest order of child elements have appeared so far. 803 */ 804 int getLastOrder() 805 { 806 return m_lastOrder; 807 } 808 809 /** 810 * Set the highest order of child elements have appeared so far . 811 * 812 * @param order the highest order of child elements have appeared so far. 813 */ 814 void setLastOrder(int order) 815 { 816 m_lastOrder = order ; 817 } 818 819 /** 820 * True if this element can appear multiple times 821 */ 822 private boolean m_multiAllowed = true; 823 824 /** 825 * Get whether this element can appear multiple times 826 * 827 * @return true if this element can appear multiple times 828 */ 829 boolean getMultiAllowed() 830 { 831 return m_multiAllowed; 832 } 833 } 834