View Javadoc

1   /*   Copyright 2004 The Apache Software Foundation
2    *
3    *   Licensed under the Apache License, Version 2.0 (the "License");
4    *   you may not use this file except in compliance with the License.
5    *   You may obtain a copy of the License at
6    *
7    *       http://www.apache.org/licenses/LICENSE-2.0
8    *
9    *   Unless required by applicable law or agreed to in writing, software
10   *   distributed under the License is distributed on an "AS IS" BASIS,
11   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   *   See the License for the specific language governing permissions and
13   *  limitations under the License.
14   */
15  
16  package com.eviware.soapui.impl.wsdl.support.xsd;
17  
18  /***
19   * XmlBeans class for generating XML from XML Schemas
20   * 
21  *  Comment on enumerations?
22  *  Comment on facets?
23  *  Have a verbose option?
24  *  Have a sample data option, would create valid instance with sample data?
25  *  Add the pattern facet; this is tricky, considering the relationship with length
26  */
27  
28  import java.math.BigDecimal;
29  import java.math.BigInteger;
30  import java.util.ArrayList;
31  import java.util.Arrays;
32  import java.util.Calendar;
33  import java.util.Date;
34  import java.util.HashSet;
35  import java.util.Random;
36  import java.util.Set;
37  
38  import javax.xml.namespace.QName;
39  
40  import org.apache.xmlbeans.GDate;
41  import org.apache.xmlbeans.GDateBuilder;
42  import org.apache.xmlbeans.GDuration;
43  import org.apache.xmlbeans.GDurationBuilder;
44  import org.apache.xmlbeans.SchemaLocalElement;
45  import org.apache.xmlbeans.SchemaParticle;
46  import org.apache.xmlbeans.SchemaProperty;
47  import org.apache.xmlbeans.SchemaType;
48  import org.apache.xmlbeans.SimpleValue;
49  import org.apache.xmlbeans.XmlAnySimpleType;
50  import org.apache.xmlbeans.XmlCursor;
51  import org.apache.xmlbeans.XmlDate;
52  import org.apache.xmlbeans.XmlDateTime;
53  import org.apache.xmlbeans.XmlDecimal;
54  import org.apache.xmlbeans.XmlDuration;
55  import org.apache.xmlbeans.XmlGDay;
56  import org.apache.xmlbeans.XmlGMonth;
57  import org.apache.xmlbeans.XmlGMonthDay;
58  import org.apache.xmlbeans.XmlGYear;
59  import org.apache.xmlbeans.XmlGYearMonth;
60  import org.apache.xmlbeans.XmlInteger;
61  import org.apache.xmlbeans.XmlObject;
62  import org.apache.xmlbeans.XmlOptions;
63  import org.apache.xmlbeans.XmlTime;
64  import org.apache.xmlbeans.impl.util.Base64;
65  import org.apache.xmlbeans.impl.util.HexBin;
66  import org.apache.xmlbeans.soap.SOAPArrayType;
67  import org.apache.xmlbeans.soap.SchemaWSDLArrayType;
68  
69  import com.eviware.soapui.SoapUI;
70  import com.eviware.soapui.settings.WsdlSettings;
71  
72  public class SampleXmlUtil
73  {
74      private boolean _soapEnc;
75      private boolean _exampleContent = false;
76      private boolean _typeComment = false;
77      private Set<QName> excludedTypes = new HashSet<QName>();
78  
79      public SampleXmlUtil(boolean soapEnc)
80      {
81          _soapEnc = soapEnc;
82          _exampleContent = SoapUI.getSettings().getBoolean(WsdlSettings.XML_GENERATION_TYPE_EXAMPLE_VALUE);
83          _typeComment = SoapUI.getSettings().getBoolean(WsdlSettings.XML_GENERATION_TYPE_COMMENT_TYPE);
84          
85          excludedTypes.addAll( SoapUI.getExcludedTypes() );
86      }
87      
88      public boolean isSoapEnc()
89      {
90         return _soapEnc;
91      }
92  
93      public boolean isExampleContent()
94  	{
95  		return _exampleContent;
96  	}
97  
98  	public void setExampleContent( boolean content )
99  	{
100 		_exampleContent = content;
101 	}
102 
103 	public boolean isTypeComment()
104 	{
105 		return _typeComment;
106 	}
107 
108 	public void setTypeComment( boolean comment )
109 	{
110 		_typeComment = comment;
111 	}
112 
113 	public String createSample(SchemaType sType)
114    {
115        XmlObject object = XmlObject.Factory.newInstance();
116        XmlCursor cursor = object.newCursor();
117        // Skip the document node
118        cursor.toNextToken();
119        // Using the type and the cursor, call the utility method to get a
120        // sample XML payload for that Schema element
121        createSampleForType(sType, cursor);
122        // Cursor now contains the sample payload
123        // Pretty print the result.  Note that the cursor is positioned at the
124        // end of the doc so we use the original xml object that the cursor was
125        // created upon to do the xmlText() against.
126        
127        cursor.dispose();
128        
129        XmlOptions options = new XmlOptions();
130        options.put(XmlOptions.SAVE_PRETTY_PRINT);
131        options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT, 3);
132        options.put(XmlOptions.SAVE_AGGRESSIVE_NAMESPACES);
133        options.setSaveOuter();
134        String result = object.xmlText(options);
135        
136        return result;
137    }
138 	
139 	public static String createSampleForType(SchemaType sType)
140     {
141         XmlObject object = XmlObject.Factory.newInstance();
142         XmlCursor cursor = object.newCursor();
143         // Skip the document node
144         cursor.toNextToken();
145         // Using the type and the cursor, call the utility method to get a
146         // sample XML payload for that Schema element
147         new SampleXmlUtil(false).createSampleForType(sType, cursor);
148         // Cursor now contains the sample payload
149         // Pretty print the result.  Note that the cursor is positioned at the
150         // end of the doc so we use the original xml object that the cursor was
151         // created upon to do the xmlText() against.
152         
153         cursor.dispose();
154         XmlOptions options = new XmlOptions();
155         options.put(XmlOptions.SAVE_PRETTY_PRINT);
156         options.put(XmlOptions.SAVE_PRETTY_PRINT_INDENT, 3);
157         options.put(XmlOptions.SAVE_AGGRESSIVE_NAMESPACES);
158         options.setSaveOuter();
159         String result = object.xmlText(options);
160         
161         return result;
162     }
163 
164     Random _picker = new Random(1);
165 
166 
167 
168 	private boolean ignoreOptional;
169 
170     /***
171      * Cursor position
172      * Before:
173      * <theElement>^</theElement>
174      * After:
175      * <theElement><lots of stuff/>^</theElement>
176      */
177     @SuppressWarnings("unchecked")
178 	public void createSampleForType(SchemaType stype, XmlCursor xmlc)
179     {
180    	 QName nm = stype.getName();
181    	 if( nm == null && stype.getContainerField() != null )
182    		 nm = stype.getContainerField().getName();
183    	 
184    	 if( nm != null && excludedTypes.contains( nm ))
185    	 {
186    		 xmlc.insertComment( "Ignoring type [" + nm + "]" );
187    		 return;
188    	 }
189    	 
190         if (_typeStack.contains( stype ))
191             return;
192 
193         _typeStack.add( stype );
194         
195         try
196         {
197             if (stype.isSimpleType() || stype.isURType())
198             {
199                 processSimpleType(stype, xmlc);
200                 return;
201             }
202             
203             // complex Type
204             // <theElement>^</theElement>
205             processAttributes(stype, xmlc);
206             
207             // <theElement attri1="string">^</theElement>
208             switch (stype.getContentType())
209             {
210                 case SchemaType.NOT_COMPLEX_TYPE :
211                 case SchemaType.EMPTY_CONTENT :
212                     // noop
213                     break;
214                 case SchemaType.SIMPLE_CONTENT :
215                     {
216                         processSimpleType(stype, xmlc);
217                     }
218                     break;
219                 case SchemaType.MIXED_CONTENT :
220                     xmlc.insertChars(pick(WORDS) + " ");
221                     if (stype.getContentModel() != null)
222                     {
223                         processParticle(stype.getContentModel(), xmlc, true);
224                     }
225                     xmlc.insertChars(pick(WORDS));
226                     break;
227                 case SchemaType.ELEMENT_CONTENT :
228                     if (stype.getContentModel() != null)
229                     {
230                         processParticle(stype.getContentModel(), xmlc, false);
231                     }
232                     break;
233             }
234         }
235         finally
236         {
237             _typeStack.remove( _typeStack.size() - 1 );
238         }
239     }
240 
241     private void processSimpleType(SchemaType stype, XmlCursor xmlc)
242     {
243        if (_soapEnc)
244        {
245            QName typeName = stype.getName();
246            if (typeName != null)
247            {
248                xmlc.insertAttributeWithValue(XSI_TYPE, formatQName(xmlc, typeName));
249            }
250        }
251        
252         
253         String sample = sampleDataForSimpleType(stype);
254         xmlc.insertChars(sample);
255     }
256     
257     private String sampleDataForSimpleType(SchemaType sType)
258     {
259    	 // swaRef
260    	 if( sType.getName() != null )
261    	 {
262 	    	if( sType.getName().equals( new QName( "http://ws-i.org/profiles/basic/1.1/xsd", "swaRef" )))
263 	    		return "cid:" + System.currentTimeMillis();
264 	
265 	  	 // xmime base64
266 	    	if( sType.getName().equals( new QName( "http://www.w3.org/2005/05/xmlmime", "base64Binary" )))
267 	    		return "cid:" + System.currentTimeMillis();
268 	
269 	  	 // xmime hexBinary
270 	    	if( sType.getName().equals( new QName( "http://www.w3.org/2005/05/xmlmime", "hexBinary" )))
271 	    		return "cid:" + System.currentTimeMillis();
272    	 }
273     	
274    	// if( sType != null )
275     	if (!_exampleContent)
276    		 return "?";
277    	 
278         if (XmlObject.type.equals(sType))
279             return "anyType";
280         
281         if (XmlAnySimpleType.type.equals(sType))
282             return "anySimpleType";
283         
284         if (sType.getSimpleVariety() == SchemaType.LIST)
285         {
286             SchemaType itemType = sType.getListItemType();
287             StringBuffer sb = new StringBuffer();
288             int length = pickLength(sType);
289             if (length > 0)
290                 sb.append(sampleDataForSimpleType(itemType));
291             for (int i = 1; i < length; i += 1)
292             {
293                 sb.append(' ');
294                 sb.append(sampleDataForSimpleType(itemType));
295             }
296             return sb.toString(); 
297         }
298         
299         if (sType.getSimpleVariety() == SchemaType.UNION)
300         {
301             SchemaType[] possibleTypes = sType.getUnionConstituentTypes();
302             if (possibleTypes.length == 0)
303                 return "";
304             return sampleDataForSimpleType(possibleTypes[pick(possibleTypes.length)]);
305         }
306         
307         XmlAnySimpleType[] enumValues = sType.getEnumerationValues();
308         if (enumValues != null && enumValues.length > 0)
309         {
310             return enumValues[pick(enumValues.length)].getStringValue();
311         }
312         
313         switch (sType.getPrimitiveType().getBuiltinTypeCode())
314         {
315             default:
316             case SchemaType.BTC_NOT_BUILTIN:
317                 return "";
318             
319             case SchemaType.BTC_ANY_TYPE:
320             case SchemaType.BTC_ANY_SIMPLE:
321                 return "anything";
322                 
323             case SchemaType.BTC_BOOLEAN:
324                 return pick(2) == 0 ? "true" : "false";
325                 
326             case SchemaType.BTC_BASE_64_BINARY:
327             {
328                 String result = null;
329                 try
330                 {   result = new String(Base64.encode(formatToLength(pick(WORDS), sType).getBytes("utf-8"))); }
331                 catch (java.io.UnsupportedEncodingException e) {}
332                 return result;
333             }
334                 
335             case SchemaType.BTC_HEX_BINARY:
336                 return HexBin.encode(formatToLength(pick(WORDS), sType));
337                 
338             case SchemaType.BTC_ANY_URI:
339                 return formatToLength("http://www." + pick(DNS1) + "." + pick(DNS2) + "/" + pick(WORDS) + "/" + pick(WORDS), sType);
340                 
341             case SchemaType.BTC_QNAME:
342                 return formatToLength("qname", sType);
343                 
344             case SchemaType.BTC_NOTATION:
345                 return formatToLength("notation", sType);
346                 
347             case SchemaType.BTC_FLOAT:
348                 return "1.5E2";
349             case SchemaType.BTC_DOUBLE:
350                 return "1.051732E7";
351             case SchemaType.BTC_DECIMAL:
352                 switch (closestBuiltin(sType).getBuiltinTypeCode())
353                 {
354                     case SchemaType.BTC_SHORT:
355                         return formatDecimal("1", sType);
356                     case SchemaType.BTC_UNSIGNED_SHORT:
357                         return formatDecimal("5", sType);
358                     case SchemaType.BTC_BYTE:
359                         return formatDecimal("2", sType);
360                     case SchemaType.BTC_UNSIGNED_BYTE:
361                         return formatDecimal("6", sType);
362                     case SchemaType.BTC_INT:
363                         return formatDecimal("3", sType);
364                     case SchemaType.BTC_UNSIGNED_INT:
365                         return formatDecimal("7", sType);
366                     case SchemaType.BTC_LONG:
367                         return formatDecimal("10", sType);
368                     case SchemaType.BTC_UNSIGNED_LONG:
369                         return formatDecimal("11", sType);
370                     case SchemaType.BTC_INTEGER:
371                         return formatDecimal("100", sType);
372                     case SchemaType.BTC_NON_POSITIVE_INTEGER:
373                         return formatDecimal("-200", sType);
374                     case SchemaType.BTC_NEGATIVE_INTEGER:
375                         return formatDecimal("-201", sType);
376                     case SchemaType.BTC_NON_NEGATIVE_INTEGER:
377                         return formatDecimal("200", sType);
378                     case SchemaType.BTC_POSITIVE_INTEGER:
379                         return formatDecimal("201", sType);
380                     default:
381                     case SchemaType.BTC_DECIMAL:
382                         return formatDecimal("1000.00", sType);
383                 }
384                 
385             case SchemaType.BTC_STRING:
386                 {
387                     String result;
388                     switch (closestBuiltin(sType).getBuiltinTypeCode())
389                     {
390                         case SchemaType.BTC_STRING:
391                         case SchemaType.BTC_NORMALIZED_STRING:
392                             result = pick(WORDS, _picker.nextInt(3));
393                             break;
394                             
395                         case SchemaType.BTC_TOKEN:
396                             result = pick(WORDS, _picker.nextInt(3));
397                             break;
398                             
399                         default:
400                             result = pick(WORDS, _picker.nextInt(3));
401                             break;
402                     }
403                         
404                     return formatToLength(result, sType);
405                 }
406 
407             case SchemaType.BTC_DURATION:
408                 return formatDuration(sType);
409                 
410             case SchemaType.BTC_DATE_TIME:
411             case SchemaType.BTC_TIME:
412             case SchemaType.BTC_DATE:
413             case SchemaType.BTC_G_YEAR_MONTH:
414             case SchemaType.BTC_G_YEAR:
415             case SchemaType.BTC_G_MONTH_DAY:
416             case SchemaType.BTC_G_DAY:
417             case SchemaType.BTC_G_MONTH:
418                 return formatDate(sType);
419                 
420         }
421     }
422     
423     // a bit from the Aenid
424     public static final String[] WORDS = new String[]
425     {
426     "ipsa", "iovis", "rapidum", "iaculata", "e", "nubibus", "ignem",
427     "disiecitque", "rates", "evertitque", "aequora", "ventis",
428     "illum", "exspirantem", "transfixo", "pectore", "flammas",
429     "turbine", "corripuit", "scopuloque", "infixit", "acuto",
430     "ast", "ego", "quae", "divum", "incedo", "regina", "iovisque",
431     "et", "soror", "et", "coniunx", "una", "cum", "gente", "tot", "annos",
432     "bella", "gero", "et", "quisquam", "numen", "iunonis", "adorat",
433     "praeterea", "aut", "supplex", "aris", "imponet", "honorem",
434     "talia", "flammato", "secum", "dea", "corde", "volutans",
435     "nimborum", "in", "patriam", "loca", "feta", "furentibus", "austris",
436     "aeoliam", "venit", "hic", "vasto", "rex", "aeolus", "antro",
437     "luctantis", "ventos", "tempestatesque", "sonoras",
438     "imperio", "premit", "ac", "vinclis", "et", "carcere", "frenat",
439     "illi", "indignantes", "magno", "cum", "murmure", "montis",
440     "circum", "claustra", "fremunt", "celsa", "sedet", "aeolus", "arce",
441     "sceptra", "tenens", "mollitque", "animos", "et", "temperat", "iras",
442     "ni", "faciat", "maria", "ac", "terras", "caelumque", "profundum",
443     "quippe", "ferant", "rapidi", "secum", "verrantque", "per", "auras",
444     "sed", "pater", "omnipotens", "speluncis", "abdidit", "atris",
445     "hoc", "metuens", "molemque", "et", "montis", "insuper", "altos",
446     "imposuit", "regemque", "dedit", "qui", "foedere", "certo",
447     "et", "premere", "et", "laxas", "sciret", "dare", "iussus", "habenas",
448     };
449     
450     
451     
452     private static final String[] DNS1 = new String[] { "corp", "your", "my", "sample", "company", "test", "any" };
453     private static final String[] DNS2 = new String[] { "com", "org", "com", "gov", "org", "com", "org", "com", "edu" };
454                                                        
455     private int pick(int n)
456     {
457         return _picker.nextInt(n);
458     }
459     
460     private String pick(String[] a)
461     {
462         return a[pick(a.length)];
463     }
464     
465     private String pick(String[] a, int count)
466     {
467         if (count <= 0)
468         	count = 1;
469 //            return "";
470             
471         int i = pick(a.length);
472         StringBuffer sb = new StringBuffer(a[i]);
473         while (count-- > 0)
474         {
475             i += 1;
476             if (i >= a.length)
477                 i = 0;
478             sb.append(' ');
479             sb.append(a[i]);
480         }
481         return sb.toString();
482     }
483     
484     private String pickDigits(int digits)
485     {
486         StringBuffer sb = new StringBuffer();
487         while (digits-- > 0)
488             sb.append(Integer.toString(pick(10)));
489         return sb.toString();
490     }
491 
492     private int pickLength(SchemaType sType)
493     {
494         XmlInteger length = (XmlInteger) sType.getFacet(SchemaType.FACET_LENGTH);
495         if (length != null)
496             return length.getBigIntegerValue().intValue();
497         XmlInteger min    = (XmlInteger) sType.getFacet(SchemaType.FACET_MIN_LENGTH);
498         XmlInteger max    = (XmlInteger) sType.getFacet(SchemaType.FACET_MAX_LENGTH);
499         int minInt, maxInt;
500         if (min == null)
501             minInt = 0;
502         else
503             minInt = min.getBigIntegerValue().intValue();
504         if (max == null)
505             maxInt = Integer.MAX_VALUE;
506         else
507             maxInt = max.getBigIntegerValue().intValue();
508         // We try to keep the length of the array within reasonable limits,
509         // at least 1 item and at most 3 if possible
510         if (minInt == 0 && maxInt >= 1)
511             minInt = 1;
512         if (maxInt > minInt + 2)
513             maxInt = minInt + 2;
514         if (maxInt < minInt)
515             maxInt = minInt;
516         return minInt + pick(maxInt-minInt);
517     }
518 
519     /***
520      * Formats a given string to the required length, using the following operations:
521      * - append the source string to itself as necessary to pass the minLength;
522      * - truncate the result of previous step, if necessary, to keep it within minLength.
523      */
524     private String formatToLength(String s, SchemaType sType)
525     {
526         String result = s;
527         try
528         {
529             SimpleValue min = (SimpleValue)sType.getFacet(SchemaType.FACET_LENGTH);
530             if (min == null)
531                 min = (SimpleValue)sType.getFacet(SchemaType.FACET_MIN_LENGTH);
532             if (min != null)
533             {
534                 int len = min.getIntValue();
535                 while (result.length() < len)
536                     result = result + result;
537             }
538             SimpleValue max = (SimpleValue)sType.getFacet(SchemaType.FACET_LENGTH);
539             if (max == null)
540                 max = (SimpleValue)sType.getFacet(SchemaType.FACET_MAX_LENGTH);
541             if (max != null)
542             {
543                 int len = max.getIntValue();
544                 if (result.length() > len)
545                     result = result.substring(0, len);
546             }
547         }
548         catch (Exception e) // intValue can be out of range
549         {
550         }
551         return result;
552     }
553 
554     private String formatDecimal(String start, SchemaType sType)
555     {
556         BigDecimal result = new BigDecimal(start);
557         XmlDecimal xmlD;
558         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
559         BigDecimal min = xmlD != null ? xmlD.getBigDecimalValue() : null;
560         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
561         BigDecimal max = xmlD != null ? xmlD.getBigDecimalValue() : null;
562         boolean minInclusive = true, maxInclusive = true;
563         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
564         if (xmlD != null)
565         {
566             BigDecimal minExcl = xmlD.getBigDecimalValue();
567             if (min == null || min.compareTo(minExcl) < 0)
568             {
569                 min = minExcl;
570                 minInclusive = false;
571             }
572         }
573         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
574         if (xmlD != null)
575         {
576             BigDecimal maxExcl = xmlD.getBigDecimalValue();
577             if (max == null || max.compareTo(maxExcl) > 0)
578             {
579                 max = maxExcl;
580                 maxInclusive = false;
581             }
582         }
583         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_TOTAL_DIGITS);
584         int totalDigits = -1;
585         if (xmlD != null)
586         {
587             totalDigits = xmlD.getBigDecimalValue().intValue();
588 
589             StringBuffer sb = new StringBuffer(totalDigits);
590             for (int i = 0; i < totalDigits; i++)
591                 sb.append('9');
592             BigDecimal digitsLimit = new BigDecimal(sb.toString());
593             if (max != null && max.compareTo(digitsLimit) > 0)
594             {
595                 max = digitsLimit;
596                 maxInclusive = true;
597             }
598             digitsLimit = digitsLimit.negate();
599             if (min != null && min.compareTo(digitsLimit) < 0)
600             {
601                 min = digitsLimit;
602                 minInclusive = true;
603             }
604         }
605 
606         int sigMin = min == null ? 1 : result.compareTo(min);
607         int sigMax = max == null ? -1 : result.compareTo(max);
608         boolean minOk = sigMin > 0 || sigMin == 0 && minInclusive;
609         boolean maxOk = sigMax < 0 || sigMax == 0 && maxInclusive;
610 
611         // Compute the minimum increment
612         xmlD = (XmlDecimal) sType.getFacet(SchemaType.FACET_FRACTION_DIGITS);
613         int fractionDigits = -1;
614         BigDecimal increment;
615         if (xmlD == null)
616             increment = new BigDecimal(1);
617         else
618         {
619             fractionDigits = xmlD.getBigDecimalValue().intValue();
620             if (fractionDigits > 0)
621             {
622                 StringBuffer sb = new StringBuffer("0.");
623                 for (int i = 1; i < fractionDigits; i++)
624                     sb.append('0');
625                 sb.append('1');
626                 increment = new BigDecimal(sb.toString());
627             }
628             else
629                 increment = new BigDecimal(1);
630         }
631 
632         if (minOk && maxOk)
633         {
634             // OK 
635         }
636         else if (minOk && !maxOk)
637         {
638             // TOO BIG
639             if (maxInclusive)
640                 result = max;
641             else
642                 result = max.subtract(increment);
643         }
644         else if (!minOk && maxOk)
645         {
646             // TOO SMALL
647             if (minInclusive)
648                 result = min;
649             else
650                 result = min.add(increment);
651         }
652         else
653         {
654             // MIN > MAX!!
655         }
656 
657         // We have the number
658         // Adjust the scale according to the totalDigits and fractionDigits
659         int digits = 0;
660         BigDecimal ONE = new BigDecimal(BigInteger.ONE);
661         for (BigDecimal n = result; n.abs().compareTo(ONE) >= 0; digits++)
662             n = n.movePointLeft(1);
663 
664         if (fractionDigits > 0)
665             if (totalDigits >= 0)
666                 result.setScale(Math.max(fractionDigits, totalDigits - digits));
667             else
668                 result.setScale(fractionDigits);
669         else if (fractionDigits == 0)
670             result.setScale(0);
671 
672         return result.toString();
673     }
674 
675     private String formatDuration(SchemaType sType)
676     {
677         XmlDuration d =
678             (XmlDuration) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
679         GDuration minInclusive = null;
680         if (d != null)
681             minInclusive = d.getGDurationValue();
682 
683         d = (XmlDuration) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
684         GDuration maxInclusive = null;
685         if (d != null)
686             maxInclusive = d.getGDurationValue();
687 
688         d = (XmlDuration) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
689         GDuration minExclusive = null;
690         if (d != null)
691             minExclusive = d.getGDurationValue();
692 
693         d = (XmlDuration) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
694         GDuration maxExclusive = null;
695         if (d != null)
696             maxExclusive = d.getGDurationValue();
697 
698         GDurationBuilder gdurb = new GDurationBuilder();
699         BigInteger min, max;
700 
701         gdurb.setSecond(pick(800000));
702         gdurb.setMonth(pick(20));
703 
704         // Years
705         // Months
706         // Days
707         // Hours
708         // Minutes
709         // Seconds
710         // Fractions
711         if (minInclusive != null)
712         {
713             if (gdurb.getYear() < minInclusive.getYear())
714                 gdurb.setYear(minInclusive.getYear());
715             if (gdurb.getMonth() < minInclusive.getMonth())
716                 gdurb.setMonth(minInclusive.getMonth());
717             if (gdurb.getDay() < minInclusive.getDay())
718                 gdurb.setDay(minInclusive.getDay());
719             if (gdurb.getHour() < minInclusive.getHour())
720                 gdurb.setHour(minInclusive.getHour());
721             if (gdurb.getMinute() < minInclusive.getMinute())
722                 gdurb.setMinute(minInclusive.getMinute());
723             if (gdurb.getSecond() < minInclusive.getSecond())
724                 gdurb.setSecond(minInclusive.getSecond());
725             if (gdurb.getFraction().compareTo(minInclusive.getFraction()) < 0)
726                 gdurb.setFraction(minInclusive.getFraction());
727         }
728 
729         if (maxInclusive != null)
730         {
731             if (gdurb.getYear() > maxInclusive.getYear())
732                 gdurb.setYear(maxInclusive.getYear());
733             if (gdurb.getMonth() > maxInclusive.getMonth())
734                 gdurb.setMonth(maxInclusive.getMonth());
735             if (gdurb.getDay() > maxInclusive.getDay())
736                 gdurb.setDay(maxInclusive.getDay());
737             if (gdurb.getHour() > maxInclusive.getHour())
738                 gdurb.setHour(maxInclusive.getHour());
739             if (gdurb.getMinute() > maxInclusive.getMinute())
740                 gdurb.setMinute(maxInclusive.getMinute());
741             if (gdurb.getSecond() > maxInclusive.getSecond())
742                 gdurb.setSecond(maxInclusive.getSecond());
743             if (gdurb.getFraction().compareTo(maxInclusive.getFraction()) > 0)
744                 gdurb.setFraction(maxInclusive.getFraction());
745         }
746 
747         if (minExclusive != null)
748         {
749             if (gdurb.getYear() <= minExclusive.getYear())
750                 gdurb.setYear(minExclusive.getYear()+1);
751             if (gdurb.getMonth() <= minExclusive.getMonth())
752                 gdurb.setMonth(minExclusive.getMonth()+1);
753             if (gdurb.getDay() <= minExclusive.getDay())
754                 gdurb.setDay(minExclusive.getDay()+1);
755             if (gdurb.getHour() <= minExclusive.getHour())
756                 gdurb.setHour(minExclusive.getHour()+1);
757             if (gdurb.getMinute() <= minExclusive.getMinute())
758                 gdurb.setMinute(minExclusive.getMinute()+1);
759             if (gdurb.getSecond() <= minExclusive.getSecond())
760                 gdurb.setSecond(minExclusive.getSecond()+1);
761             if (gdurb.getFraction().compareTo(minExclusive.getFraction()) <= 0)
762                 gdurb.setFraction(minExclusive.getFraction().add(new BigDecimal(0.001)));
763         }
764 
765         if (maxExclusive != null)
766         {
767             if (gdurb.getYear() > maxExclusive.getYear())
768                 gdurb.setYear(maxExclusive.getYear());
769             if (gdurb.getMonth() > maxExclusive.getMonth())
770                 gdurb.setMonth(maxExclusive.getMonth());
771             if (gdurb.getDay() > maxExclusive.getDay())
772                 gdurb.setDay(maxExclusive.getDay());
773             if (gdurb.getHour() > maxExclusive.getHour())
774                 gdurb.setHour(maxExclusive.getHour());
775             if (gdurb.getMinute() > maxExclusive.getMinute())
776                 gdurb.setMinute(maxExclusive.getMinute());
777             if (gdurb.getSecond() > maxExclusive.getSecond())
778                 gdurb.setSecond(maxExclusive.getSecond());
779             if (gdurb.getFraction().compareTo(maxExclusive.getFraction()) > 0)
780                 gdurb.setFraction(maxExclusive.getFraction());
781         }
782 
783         gdurb.normalize();
784         return gdurb.toString();
785     }
786 
787     private String formatDate(SchemaType sType)
788     {
789         GDateBuilder gdateb = new GDateBuilder(new Date(1000L * pick(365 * 24 * 60 * 60) + (30L + pick(20)) * 365 * 24 * 60 * 60 * 1000));
790         GDate min = null, max = null;
791         GDate temp;
792 
793         // Find the min and the max according to the type
794         switch (sType.getPrimitiveType().getBuiltinTypeCode())
795         {
796             case SchemaType.BTC_DATE_TIME:
797             {
798                 XmlDateTime x = (XmlDateTime) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
799                 if (x != null)
800                     min = x.getGDateValue();
801                 x = (XmlDateTime) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
802                 if (x != null)
803                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
804                         min = x.getGDateValue();
805 
806                 x = (XmlDateTime) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
807                 if (x != null)
808                     max = x.getGDateValue();
809                 x = (XmlDateTime) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
810                 if (x != null)
811                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
812                         max = x.getGDateValue();
813                 break;
814             }
815             case SchemaType.BTC_TIME:
816             {
817                 XmlTime x = (XmlTime) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
818                 if (x != null)
819                     min = x.getGDateValue();
820                 x = (XmlTime) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
821                 if (x != null)
822                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
823                         min = x.getGDateValue();
824 
825                 x = (XmlTime) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
826                 if (x != null)
827                     max = x.getGDateValue();
828                 x = (XmlTime) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
829                 if (x != null)
830                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
831                         max = x.getGDateValue();
832                 break;
833             }
834             case SchemaType.BTC_DATE:
835             {
836                 XmlDate x = (XmlDate) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
837                 if (x != null)
838                     min = x.getGDateValue();
839                 x = (XmlDate) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
840                 if (x != null)
841                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
842                         min = x.getGDateValue();
843 
844                 x = (XmlDate) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
845                 if (x != null)
846                     max = x.getGDateValue();
847                 x = (XmlDate) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
848                 if (x != null)
849                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
850                         max = x.getGDateValue();
851                 break;
852             }
853             case SchemaType.BTC_G_YEAR_MONTH:
854             {
855                 XmlGYearMonth x = (XmlGYearMonth) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
856                 if (x != null)
857                     min = x.getGDateValue();
858                 x = (XmlGYearMonth) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
859                 if (x != null)
860                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
861                         min = x.getGDateValue();
862 
863                 x = (XmlGYearMonth) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
864                 if (x != null)
865                     max = x.getGDateValue();
866                 x = (XmlGYearMonth) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
867                 if (x != null)
868                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
869                         max = x.getGDateValue();
870                 break;
871             }
872             case SchemaType.BTC_G_YEAR:
873             {
874                 XmlGYear x = (XmlGYear) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
875                 if (x != null)
876                     min = x.getGDateValue();
877                 x = (XmlGYear) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
878                 if (x != null)
879                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
880                         min = x.getGDateValue();
881 
882                 x = (XmlGYear) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
883                 if (x != null)
884                     max = x.getGDateValue();
885                 x = (XmlGYear) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
886                 if (x != null)
887                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
888                         max = x.getGDateValue();
889                 break;
890             }
891             case SchemaType.BTC_G_MONTH_DAY:
892             {
893                 XmlGMonthDay x = (XmlGMonthDay) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
894                 if (x != null)
895                     min = x.getGDateValue();
896                 x = (XmlGMonthDay) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
897                 if (x != null)
898                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
899                         min = x.getGDateValue();
900 
901                 x = (XmlGMonthDay) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
902                 if (x != null)
903                     max = x.getGDateValue();
904                 x = (XmlGMonthDay) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
905                 if (x != null)
906                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
907                         max = x.getGDateValue();
908                 break;
909             }
910             case SchemaType.BTC_G_DAY:
911             {
912                 XmlGDay x = (XmlGDay) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
913                 if (x != null)
914                     min = x.getGDateValue();
915                 x = (XmlGDay) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
916                 if (x != null)
917                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
918                         min = x.getGDateValue();
919 
920                 x = (XmlGDay) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
921                 if (x != null)
922                     max = x.getGDateValue();
923                 x = (XmlGDay) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
924                 if (x != null)
925                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
926                         max = x.getGDateValue();
927                 break;
928             }
929             case SchemaType.BTC_G_MONTH:
930             {
931                 XmlGMonth x = (XmlGMonth) sType.getFacet(SchemaType.FACET_MIN_INCLUSIVE);
932                 if (x != null)
933                     min = x.getGDateValue();
934                 x = (XmlGMonth) sType.getFacet(SchemaType.FACET_MIN_EXCLUSIVE);
935                 if (x != null)
936                     if (min == null || min.compareToGDate(x.getGDateValue()) <= 0)
937                         min = x.getGDateValue();
938 
939                 x = (XmlGMonth) sType.getFacet(SchemaType.FACET_MAX_INCLUSIVE);
940                 if (x != null)
941                     max = x.getGDateValue();
942                 x = (XmlGMonth) sType.getFacet(SchemaType.FACET_MAX_EXCLUSIVE);
943                 if (x != null)
944                     if (max == null || max.compareToGDate(x.getGDateValue()) >= 0)
945                         max = x.getGDateValue();
946                 break;
947             }
948         }
949 
950         if (min != null && max == null)
951         {
952             if (min.compareToGDate(gdateb) >= 0)
953             {
954                 // Reset the date to min + (1-8) hours
955                 Calendar c = gdateb.getCalendar();
956                 c.add(Calendar.HOUR_OF_DAY, pick(8));
957                 gdateb = new GDateBuilder(c);
958             }
959         }
960         else if (min == null && max != null)
961         {
962             if (max.compareToGDate(gdateb) <= 0)
963             {
964                 // Reset the date to max - (1-8) hours
965                 Calendar c = gdateb.getCalendar();
966                 c.add(Calendar.HOUR_OF_DAY, 0-pick(8));
967                 gdateb = new GDateBuilder(c);
968             }
969         }
970         else if (min != null && max != null)
971         {
972             if (min.compareToGDate(gdateb) >= 0 || max.compareToGDate(gdateb) <= 0)
973             {
974                 // Find a date between the two
975                 Calendar c = min.getCalendar();
976                 Calendar cmax = max.getCalendar();
977                 c.add(Calendar.HOUR_OF_DAY, 1);
978                 if (c.after(cmax))
979                 {
980                     c.add(Calendar.HOUR_OF_DAY, -1);
981                     c.add(Calendar.MINUTE, 1);
982                     if (c.after(cmax))
983                     {
984                         c.add(Calendar.MINUTE, -1);
985                         c.add(Calendar.SECOND, 1);
986                         if (c.after(cmax))
987                         {
988                             c.add(Calendar.SECOND, -1);
989                             c.add(Calendar.MILLISECOND, 1);
990                             if (c.after(cmax))
991                                 c.add(Calendar.MILLISECOND, -1);
992                         }
993                     }
994                 }
995                 gdateb = new GDateBuilder(c);
996             }
997         }
998 
999         gdateb.setBuiltinTypeCode(sType.getPrimitiveType().getBuiltinTypeCode());
1000         if (pick(2) == 0)
1001             gdateb.clearTimeZone();
1002         return gdateb.toString();
1003     }
1004 
1005     private SchemaType closestBuiltin(SchemaType sType)
1006     {
1007         while (!sType.isBuiltinType())
1008             sType = sType.getBaseType();
1009         return sType;
1010     }
1011     
1012 
1013     /***
1014      * Cracks a combined QName of the form URL:localname
1015      */
1016     public static QName crackQName(String qName)
1017     {
1018         String ns;
1019         String name;
1020 
1021         int index = qName.lastIndexOf( ':' );
1022         if (index >= 0)
1023         {
1024             ns   = qName.substring( 0, index );
1025             name = qName.substring( index + 1);
1026         }
1027         else
1028         {
1029             ns   = "";
1030             name = qName;
1031         }
1032 
1033         return new QName(ns, name);
1034     }
1035 
1036 
1037     /***
1038      * Cursor position:
1039      * Before this call:
1040      * <outer><foo/>^</outer>  (cursor at the ^)
1041      * After this call:
1042      * <<outer><foo/><bar/>som text<etc/>^</outer>
1043      */
1044     private void processParticle(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1045     {
1046         int loop = determineMinMaxForSample(sp, xmlc);
1047 
1048         while (loop-- > 0)
1049         {
1050             switch (sp.getParticleType())
1051             {
1052                 case (SchemaParticle.ELEMENT) :
1053                     processElement(sp, xmlc, mixed);
1054                     break;
1055                 case (SchemaParticle.SEQUENCE) :
1056                     processSequence(sp, xmlc, mixed);
1057                     break;
1058                 case (SchemaParticle.CHOICE) :
1059                     processChoice(sp, xmlc, mixed);
1060                     break;
1061                 case (SchemaParticle.ALL) :
1062                     processAll(sp, xmlc, mixed);
1063                     break;
1064                 case (SchemaParticle.WILDCARD) :
1065                     processWildCard(sp, xmlc, mixed);
1066                     break;
1067                 default :
1068                     // throw new Exception("No Match on Schema Particle Type: " + String.valueOf(sp.getParticleType()));
1069             }
1070         }
1071     }
1072 
1073     private int determineMinMaxForSample(SchemaParticle sp, XmlCursor xmlc)
1074     {
1075         int minOccurs = sp.getIntMinOccurs();
1076         int maxOccurs = sp.getIntMaxOccurs();
1077         
1078         if (minOccurs == maxOccurs)
1079             return minOccurs;
1080         
1081         if( minOccurs == 0 && ignoreOptional )
1082       	  return 0;
1083         
1084         int result = minOccurs;
1085         if (result == 0)
1086             result = 1;
1087         
1088         if (sp.getParticleType() != SchemaParticle.ELEMENT)
1089             return result;
1090         
1091         // it probably only makes sense to put comments in front of individual elements that repeat
1092         
1093         if (sp.getMaxOccurs() == null)
1094         {
1095             // xmlc.insertComment("The next " + getItemNameOrType(sp, xmlc) + " may be repeated " + minOccurs + " or more times");
1096             if (minOccurs == 0)
1097                 xmlc.insertComment("Zero or more repetitions:");
1098             else
1099                 xmlc.insertComment(minOccurs + " or more repetitions:");
1100         }
1101         else if (sp.getIntMaxOccurs() > 1)
1102         {
1103             xmlc.insertComment(minOccurs + " to " + String.valueOf(sp.getMaxOccurs()) + " repetitions:");
1104         }
1105         else
1106         {
1107             xmlc.insertComment("Optional:");
1108         }
1109         return result;
1110     }
1111 
1112     /*
1113      Return a name for the element or the particle type to use in the comment for minoccurs, max occurs
1114     */
1115     private String getItemNameOrType(SchemaParticle sp, XmlCursor xmlc)
1116     {
1117         String elementOrTypeName = null;
1118         if (sp.getParticleType() == SchemaParticle.ELEMENT)
1119         {
1120             elementOrTypeName = "Element (" + sp.getName().getLocalPart() + ")";
1121         }
1122         else
1123         {
1124             elementOrTypeName = printParticleType(sp.getParticleType());
1125         }
1126         return elementOrTypeName;
1127     }
1128 
1129     private void processElement(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1130     {
1131         // cast as schema local element
1132         SchemaLocalElement element = (SchemaLocalElement) sp;
1133         
1134         // Add comment about type
1135         addElementTypeAndRestricionsComment(element, xmlc);
1136         
1137         /// ^  -> <elemenname></elem>^
1138         if (_soapEnc)
1139             xmlc.insertElement(element.getName().getLocalPart()); // soap encoded? drop namespaces.
1140         else
1141             xmlc.insertElement(element.getName().getLocalPart(), element.getName().getNamespaceURI());
1142         /// -> <elem>^</elem>
1143        // processAttributes( sp.getType(), xmlc );
1144         
1145         xmlc.toPrevToken();
1146         // -> <elem>stuff^</elem>
1147 
1148         createSampleForType(element.getType(), xmlc);
1149         // -> <elem>stuff</elem>^
1150         xmlc.toNextToken();
1151 
1152     }
1153 
1154     private void moveToken(int numToMove, XmlCursor xmlc)
1155     {
1156         for (int i = 0; i < Math.abs(numToMove); i++)
1157         {
1158             if (numToMove < 0)
1159             {
1160                 xmlc.toPrevToken();
1161             }
1162             else
1163             {
1164                 xmlc.toNextToken();
1165             }
1166         }
1167     }
1168     
1169     private static final String formatQName(XmlCursor xmlc, QName qName)
1170     {
1171         XmlCursor parent = xmlc.newCursor();
1172         parent.toParent();
1173         String prefix = parent.prefixForNamespace(qName.getNamespaceURI());
1174         parent.dispose();
1175         String name;
1176         if (prefix == null || prefix.length() == 0)
1177             name = qName.getLocalPart();
1178         else
1179             name = prefix + ":" + qName.getLocalPart();
1180         return name;
1181     }
1182     
1183     private static final QName HREF = new QName("href"); 
1184     private static final QName ID = new QName("id"); 
1185     public static final QName XSI_TYPE = new QName("http://www.w3.org/2001/XMLSchema-instance", "type"); 
1186     private static final QName ENC_ARRAYTYPE = new QName("http://schemas.xmlsoap.org/soap/encoding/", "arrayType");
1187     private static final QName ENC_OFFSET = new QName("http://schemas.xmlsoap.org/soap/encoding/", "offset");
1188     
1189     private static final Set<QName> SKIPPED_SOAP_ATTRS = new HashSet<QName>(Arrays.asList(new QName[] { HREF, ID, ENC_OFFSET}));
1190     private void processAttributes(SchemaType stype, XmlCursor xmlc)
1191     {
1192         if (_soapEnc)
1193         {
1194             QName typeName = stype.getName();
1195             if (typeName != null)
1196             {
1197                 xmlc.insertAttributeWithValue(XSI_TYPE, formatQName(xmlc, typeName));
1198             }
1199         }
1200         
1201         SchemaProperty[] attrProps = stype.getAttributeProperties();
1202         for (int i = 0; i < attrProps.length; i++)
1203         {
1204             SchemaProperty attr = attrProps[i];
1205 
1206             if( attr.getName().equals( new QName( "http://www.w3.org/2005/05/xmlmime", "contentType")))
1207             {
1208             	xmlc.insertAttributeWithValue(attr.getName(), "application/?" );
1209             	continue;
1210             }
1211             
1212             if (_soapEnc)
1213             {
1214                 if (SKIPPED_SOAP_ATTRS.contains(attr.getName()))
1215                     continue;
1216                 if (ENC_ARRAYTYPE.equals(attr.getName()))
1217                 {
1218                     SOAPArrayType arrayType = ((SchemaWSDLArrayType)stype.getAttributeModel().getAttribute(attr.getName())).getWSDLArrayType();
1219                     if (arrayType != null)
1220                         xmlc.insertAttributeWithValue(attr.getName(), formatQName(xmlc, arrayType.getQName()) + arrayType.soap11DimensionString());
1221                     continue;
1222                 }
1223             }
1224             String defaultValue = attr.getDefaultText();
1225             xmlc.insertAttributeWithValue(attr.getName(), defaultValue == null ?
1226                 sampleDataForSimpleType(attr.getType()) : defaultValue);
1227         }
1228     }
1229 
1230     private void processSequence(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1231     {
1232         SchemaParticle[] spc = sp.getParticleChildren();
1233         for (int i=0; i < spc.length; i++)
1234         {
1235             /// <parent>maybestuff^</parent>
1236             processParticle(spc[i], xmlc, mixed);
1237             //<parent>maybestuff...morestuff^</parent>
1238             if (mixed && i < spc.length-1)
1239                 xmlc.insertChars(pick(WORDS));
1240         }
1241     }
1242 
1243     private void processChoice(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1244     {
1245         SchemaParticle[] spc = sp.getParticleChildren();
1246         xmlc.insertComment("You have a CHOICE of the next " + String.valueOf(spc.length) + " items at this level");
1247         for (int i=0; i < spc.length; i++)
1248         {
1249             processParticle(spc[i], xmlc, mixed);
1250         }
1251     }
1252 
1253     private void processAll(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1254     {
1255         SchemaParticle[] spc = sp.getParticleChildren();
1256         // xmlc.insertComment("You may enter the following " + String.valueOf(spc.length) + " items in any order");
1257         for (int i=0; i < spc.length; i++)
1258         {
1259             processParticle(spc[i], xmlc, mixed);
1260             if (mixed && i < spc.length-1)
1261                 xmlc.insertChars(pick(WORDS));
1262         }
1263     }
1264 
1265     private void processWildCard(SchemaParticle sp, XmlCursor xmlc, boolean mixed)
1266     {
1267         xmlc.insertComment("You may enter ANY elements at this point");
1268         //xmlc.insertElement("AnyElement");
1269     }
1270 
1271     /***
1272      * This method will get the base type for the schema type
1273      */
1274     
1275     private static QName getClosestName(SchemaType sType)
1276     {
1277         while (sType.getName() == null)
1278             sType = sType.getBaseType();
1279 
1280         return sType.getName();
1281     }
1282 
1283     private String printParticleType(int particleType)
1284     {
1285         StringBuffer returnParticleType = new StringBuffer();
1286         returnParticleType.append("Schema Particle Type: ");
1287 
1288         switch (particleType)
1289         {
1290             case SchemaParticle.ALL :
1291                 returnParticleType.append("ALL\n");
1292                 break;
1293             case SchemaParticle.CHOICE :
1294                 returnParticleType.append("CHOICE\n");
1295                 break;
1296             case SchemaParticle.ELEMENT :
1297                 returnParticleType.append("ELEMENT\n");
1298                 break;
1299             case SchemaParticle.SEQUENCE :
1300                 returnParticleType.append("SEQUENCE\n");
1301                 break;
1302             case SchemaParticle.WILDCARD :
1303                 returnParticleType.append("WILDCARD\n");
1304                 break;
1305             default :
1306                 returnParticleType.append("Schema Particle Type Unknown");
1307                 break;
1308         }
1309 
1310         return returnParticleType.toString();
1311     }
1312 
1313     private ArrayList _typeStack = new ArrayList();
1314 
1315 	public boolean isIgnoreOptional()
1316 	{
1317 		return ignoreOptional;
1318 	}
1319 
1320 	public void setIgnoreOptional(boolean ignoreOptional)
1321 	{
1322 		this.ignoreOptional = ignoreOptional;
1323 	}
1324 	
1325 	private void addElementTypeAndRestricionsComment(SchemaLocalElement element, XmlCursor xmlc) {
1326 		
1327 		SchemaType type = element.getType();
1328 		if (_typeComment && (type != null && type.isSimpleType())) 
1329 		{
1330 			String info = "";
1331 			
1332 			XmlAnySimpleType[] values = type.getEnumerationValues();
1333 			if( values != null && values.length > 0 )
1334 			{
1335 				info = " - enumeration: [";
1336 				for( int c = 0; c < values.length; c++ )
1337 				{
1338 					if( c > 0 )
1339 						info += ",";
1340 					
1341 					info += values[c].getStringValue(); 
1342 				}
1343 				
1344 				info += "]";
1345 			}
1346 				
1347 			
1348         	if( type.isAnonymousType()  )
1349         		xmlc.insertComment("anonymous type" + info );
1350         	else
1351         		xmlc.insertComment("type: " + type.getName().getLocalPart() + info);
1352         }
1353 	}
1354         
1355         
1356 }