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