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