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