36
36
import java .util .function .BiFunction ;
37
37
import java .util .function .Supplier ;
38
38
import java .util .stream .Stream ;
39
+
39
40
import javax .xml .datatype .DatatypeFactory ;
40
41
import javax .xml .datatype .Duration ;
41
42
import javax .xml .datatype .XMLGregorianCalendar ;
60
61
import org .eclipse .esmf .metamodel .characteristic .Enumeration ;
61
62
import org .eclipse .esmf .metamodel .characteristic .State ;
62
63
import org .eclipse .esmf .metamodel .characteristic .Trait ;
64
+ import org .eclipse .esmf .metamodel .constraint .FixedPointConstraint ;
63
65
import org .eclipse .esmf .metamodel .constraint .LengthConstraint ;
64
66
import org .eclipse .esmf .metamodel .constraint .RangeConstraint ;
65
67
import org .eclipse .esmf .metamodel .constraint .RegularExpressionConstraint ;
@@ -479,6 +481,9 @@ private Optional<Object> generateExampleValueForTrait( final Trait trait, final
479
481
if ( constraint .is ( RegularExpressionConstraint .class ) ) {
480
482
return Optional .of ( getRandomValue ( constraint .as ( RegularExpressionConstraint .class ) ) );
481
483
}
484
+ if ( constraint .is ( FixedPointConstraint .class ) ) {
485
+ return Optional .of ( getRandomValue ( constraint .as ( FixedPointConstraint .class ) ) );
486
+ }
482
487
}
483
488
return Optional .empty ();
484
489
}
@@ -572,6 +577,26 @@ private Number getRandomValue( final RangeConstraint rangeConstraint, final java
572
577
return generateForNumericTypeInRange ( valueType , min , max );
573
578
}
574
579
580
+ public Number getRandomValue ( final FixedPointConstraint fixedPointConstraint ) {
581
+
582
+ final int integerDigits = fixedPointConstraint .getInteger ();
583
+ final int scale = fixedPointConstraint .getScale ();
584
+
585
+ final int integerPart = getRandomInteger ( integerDigits );
586
+
587
+ if ( scale > 0 ) {
588
+ final double fractionalPart = getRandomDouble ( scale );
589
+
590
+ final double result = integerPart + fractionalPart ;
591
+
592
+ final BigDecimal roundedResult = BigDecimal .valueOf ( result )
593
+ .setScale ( scale , RoundingMode .DOWN );
594
+ return roundedResult .doubleValue ();
595
+ } else {
596
+ return integerPart ;
597
+ }
598
+ }
599
+
575
600
private Number generateForNumericTypeInRange ( final java .lang .reflect .Type valueType , final Number min , final Number max ) {
576
601
return generators
577
602
.getOrDefault ( valueType , ( low , high ) -> getRandomDouble ( low .doubleValue (), high .doubleValue () ) )
@@ -580,7 +605,7 @@ private Number generateForNumericTypeInRange( final java.lang.reflect.Type value
580
605
581
606
// narrowing conversion from BigDecimal to double
582
607
private double safelyNarrowDown ( final Number bound ) {
583
- if ( !( BigDecimal .class .equals ( bound .getClass () ) ) ) {
608
+ if ( !(BigDecimal .class .equals ( bound .getClass () )) ) {
584
609
return bound .doubleValue ();
585
610
}
586
611
@@ -589,7 +614,7 @@ private double safelyNarrowDown( final Number bound ) {
589
614
// Example: xsd:unsignedLong has a max. value of 18446744073709551615; when converting it to double
590
615
// it will get represented as 1.8446744073709552E16, thereby exceeding the upper bound.
591
616
// Therefore we need to take care of always rounding down when narrowing to double.
592
- final BigDecimal narrowed = ( (BigDecimal ) bound ).round ( new MathContext ( 15 , RoundingMode .DOWN ) );
617
+ final BigDecimal narrowed = ((BigDecimal ) bound ).round ( new MathContext ( 15 , RoundingMode .DOWN ) );
593
618
return narrowed .doubleValue ();
594
619
}
595
620
@@ -637,6 +662,15 @@ private Double getRandomDouble( final double min, final double max ) {
637
662
return random .doubles ( 1 , min , max ).findFirst ().getAsDouble ();
638
663
}
639
664
665
+ private Double getRandomDouble ( final int scale ) {
666
+ final int min = (int ) Math .pow ( 10 , scale - 1 );
667
+ final int max = (int ) Math .pow ( 10 , scale ) - 1 ;
668
+
669
+ final int fractionalValue = getRandomInteger ( min , max );
670
+
671
+ return fractionalValue / Math .pow ( 10 , scale );
672
+ }
673
+
640
674
private Integer getRandomInteger ( final int min , final int max ) {
641
675
if ( min == max ) {
642
676
return min ;
@@ -645,6 +679,21 @@ private Integer getRandomInteger( final int min, final int max ) {
645
679
return random .ints ( 1 , min , max ).findFirst ().getAsInt ();
646
680
}
647
681
682
+ /**
683
+ * Generates a random integer with the exact specified number of digits.
684
+ *
685
+ * @param countOfDigits The number of digits the generated integer should have. Must be greater than 0.
686
+ * @return A random integer with exactly {@code countOfDigits} digits.
687
+ * For example, if {@code countOfDigits} is 3, the result will be
688
+ * a number between 100 and 999 inclusive.
689
+ * @throws IllegalArgumentException If {@code countOfDigits} is less than 1.
690
+ */
691
+ private int getRandomInteger ( final int countOfDigits ) {
692
+ int min = (int ) Math .pow ( 10 , countOfDigits - 1 );
693
+ int max = (int ) Math .pow ( 10 , countOfDigits ) - 1 ;
694
+ return getRandomInteger ( min , max );
695
+ }
696
+
648
697
// We need a Long generator too, because with a RangeConstraint set to Long bounds
649
698
// we might not be able to generate legal values with just the Integer generator.
650
699
private Long getRandomLong ( final long min , final long max ) {
0 commit comments