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