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    */
XSLTElementDef()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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, boolean has_required)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, boolean has_required, boolean required)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, boolean has_required, boolean required, int order, boolean multiAllowed)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, boolean has_required, boolean required, boolean has_order, int order, boolean multiAllowed)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, boolean has_order, int order, boolean multiAllowed)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    */
XSLTElementDef(XSLTSchema schema, String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject, int order, boolean multiAllowed)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    */
XSLTElementDef(Class classObject, XSLTElementProcessor contentHandler, int type)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    */
build(String namespace, String name, String nameAlias, XSLTElementDef[] elements, XSLTAttributeDef[] attributes, XSLTElementProcessor contentHandler, Class classObject)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    */
equalsMayBeNull(Object obj1, Object obj2)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    */
equalsMayBeNullOrZeroLen(String s1, String s2)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    */
getType()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    */
setType(int t)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    */
getNamespace()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    */
getName()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    */
getNameAlias()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    */
getElements()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    */
setElements(XSLTElementDef[] defs)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    */
QNameEquals(String uri, String localName)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    */
getProcessorFor(String uri, String localName)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    */
getProcessorForUnknown(String uri, String localName)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    */
getAttributes()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    */
getAttributeDef(String uri, String localName)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    */
getElementProcessor()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    */
setElementProcessor(XSLTElementProcessor handler)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    */
getClassObject()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    */
hasRequired()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    */
getRequired()694   boolean getRequired()
695   {
696     return m_required;
697   }
698 
699 	Hashtable m_requiredFound;
700 
701 	/**
702    * Set this required element found.
703    *
704    */
setRequiredFound(String elem, boolean found)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    */
getRequiredFound()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    */
getRequiredElem()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    */
isOrdered()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    */
getOrder()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    */
getLastOrder()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    */
setLastOrder(int order)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    */
getMultiAllowed()829   boolean getMultiAllowed()
830   {
831     return m_multiAllowed;
832   }
833 }
834