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