001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: XSLTElementDef.java 468640 2006-10-28 06:53:53Z minchau $
020     */
021    package org.apache.xalan.processor;
022    
023    import java.util.Enumeration;
024    import java.util.Hashtable;
025    
026    import org.apache.xalan.templates.Constants;
027    import org.apache.xml.utils.QName;
028    
029    /**
030     * This class defines the allowed structure for an element in a XSLT stylesheet,
031     * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the
032     * mapping between Xalan classes and the markup elements in the XSLT instance.
033     * This actually represents both text nodes and elements.
034     */
035    public class XSLTElementDef
036    {
037    
038      /**
039       * Construct an instance of XSLTElementDef.  This must be followed by a
040       * call to build().
041       */
042      XSLTElementDef(){}
043    
044      /**
045       * Construct an instance of XSLTElementDef.
046       *
047       * @param namespace  The Namespace URI, "*", or null.
048       * @param name The local name (without prefix), "*", or null.
049       * @param nameAlias A potential alias for the name, or null.
050       * @param elements An array of allowed child element defs, or null.
051       * @param attributes An array of allowed attribute defs, or null.
052       * @param contentHandler The element processor for this element.
053       * @param classObject The class of the object that this element def should produce.
054       */
055      XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
056                     XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
057                     XSLTElementProcessor contentHandler, Class classObject)
058      {
059        build(namespace, name, nameAlias, elements, attributes, contentHandler,
060              classObject);
061        if ( (null != namespace)
062        &&  (namespace.equals(Constants.S_XSLNAMESPACEURL)
063            || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
064            || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL)))
065        {
066          schema.addAvailableElement(new QName(namespace, name));
067          if(null != nameAlias)
068            schema.addAvailableElement(new QName(namespace, nameAlias));
069        } 
070      }
071            
072            /**
073       * Construct an instance of XSLTElementDef.
074       *
075       * @param namespace  The Namespace URI, "*", or null.
076       * @param name The local name (without prefix), "*", or null.
077       * @param nameAlias A potential alias for the name, or null.
078       * @param elements An array of allowed child element defs, or null.
079       * @param attributes An array of allowed attribute defs, or null.
080       * @param contentHandler The element processor for this element.
081       * @param classObject The class of the object that this element def should produce.
082       * @param has_required true if this element has required elements by the XSLT specification.
083       */
084      XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias,
085                     XSLTElementDef[] elements, XSLTAttributeDef[] attributes,
086                     XSLTElementProcessor contentHandler, Class classObject, boolean has_required)
087      {
088                    this.m_has_required = has_required;
089        build(namespace, name, nameAlias, elements, attributes, contentHandler,
090              classObject);
091        if ( (null != namespace)
092        &&  (namespace.equals(Constants.S_XSLNAMESPACEURL)
093            || namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
094            || namespace.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL)))
095        {
096          schema.addAvailableElement(new QName(namespace, name));
097          if(null != nameAlias)
098            schema.addAvailableElement(new QName(namespace, nameAlias));
099        } 
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    }