Skip to content

Commit f09da9b

Browse files
authored
Merge pull request #698 from bci-oss/697-add-fixed-point-constraint-for-generation-json
Add fixed point constraint for generation example value
2 parents dfee56f + 7656f34 commit f09da9b

File tree

5 files changed

+147
-34
lines changed

5 files changed

+147
-34
lines changed

core/esmf-aspect-meta-model-java/src/test/java/org/eclipse/esmf/aspectmodel/loader/FixedPointConstraintInstantiatorTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222

2323
import org.junit.jupiter.api.Test;
2424

25-
public class FixedPointConstraintInstantiatorTest extends AbstractAspectModelInstantiatorTest {
25+
class FixedPointConstraintInstantiatorTest extends AbstractAspectModelInstantiatorTest {
2626
@Test
27-
public void testFixedPointConstraintInstantiationExpectSuccess() {
27+
void testFixedPointConstraintInstantiationExpectSuccess() {
2828
final Aspect aspect = loadAspect( TestAspect.ASPECT_WITH_FIXED_POINT );
2929
final Trait trait = (Trait) aspect.getProperties().get( 0 ).getCharacteristic().get();
3030
final FixedPointConstraint fixedPointConstraint = (FixedPointConstraint) trait.getConstraints().get( 0 );

core/esmf-aspect-model-document-generators/src/main/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGenerator.java

+51-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.function.BiFunction;
3737
import java.util.function.Supplier;
3838
import java.util.stream.Stream;
39+
3940
import javax.xml.datatype.DatatypeFactory;
4041
import javax.xml.datatype.Duration;
4142
import javax.xml.datatype.XMLGregorianCalendar;
@@ -60,6 +61,7 @@
6061
import org.eclipse.esmf.metamodel.characteristic.Enumeration;
6162
import org.eclipse.esmf.metamodel.characteristic.State;
6263
import org.eclipse.esmf.metamodel.characteristic.Trait;
64+
import org.eclipse.esmf.metamodel.constraint.FixedPointConstraint;
6365
import org.eclipse.esmf.metamodel.constraint.LengthConstraint;
6466
import org.eclipse.esmf.metamodel.constraint.RangeConstraint;
6567
import org.eclipse.esmf.metamodel.constraint.RegularExpressionConstraint;
@@ -479,6 +481,9 @@ private Optional<Object> generateExampleValueForTrait( final Trait trait, final
479481
if ( constraint.is( RegularExpressionConstraint.class ) ) {
480482
return Optional.of( getRandomValue( constraint.as( RegularExpressionConstraint.class ) ) );
481483
}
484+
if ( constraint.is( FixedPointConstraint.class ) ) {
485+
return Optional.of( getRandomValue( constraint.as( FixedPointConstraint.class ) ) );
486+
}
482487
}
483488
return Optional.empty();
484489
}
@@ -572,6 +577,26 @@ private Number getRandomValue( final RangeConstraint rangeConstraint, final java
572577
return generateForNumericTypeInRange( valueType, min, max );
573578
}
574579

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+
575600
private Number generateForNumericTypeInRange( final java.lang.reflect.Type valueType, final Number min, final Number max ) {
576601
return generators
577602
.getOrDefault( valueType, ( low, high ) -> getRandomDouble( low.doubleValue(), high.doubleValue() ) )
@@ -580,7 +605,7 @@ private Number generateForNumericTypeInRange( final java.lang.reflect.Type value
580605

581606
// narrowing conversion from BigDecimal to double
582607
private double safelyNarrowDown( final Number bound ) {
583-
if ( !( BigDecimal.class.equals( bound.getClass() ) ) ) {
608+
if ( !(BigDecimal.class.equals( bound.getClass() )) ) {
584609
return bound.doubleValue();
585610
}
586611

@@ -589,7 +614,7 @@ private double safelyNarrowDown( final Number bound ) {
589614
// Example: xsd:unsignedLong has a max. value of 18446744073709551615; when converting it to double
590615
// it will get represented as 1.8446744073709552E16, thereby exceeding the upper bound.
591616
// 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 ) );
593618
return narrowed.doubleValue();
594619
}
595620

@@ -637,6 +662,15 @@ private Double getRandomDouble( final double min, final double max ) {
637662
return random.doubles( 1, min, max ).findFirst().getAsDouble();
638663
}
639664

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+
640674
private Integer getRandomInteger( final int min, final int max ) {
641675
if ( min == max ) {
642676
return min;
@@ -645,6 +679,21 @@ private Integer getRandomInteger( final int min, final int max ) {
645679
return random.ints( 1, min, max ).findFirst().getAsInt();
646680
}
647681

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+
648697
// We need a Long generator too, because with a RangeConstraint set to Long bounds
649698
// we might not be able to generate legal values with just the Integer generator.
650699
private Long getRandomLong( final long min, final long max ) {

core/esmf-aspect-model-document-generators/src/test/java/org/eclipse/esmf/aspectmodel/generator/json/AspectModelJsonPayloadGeneratorTest.java

+10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.stream.IntStream;
3838
import java.util.stream.LongStream;
3939
import java.util.stream.Stream;
40+
4041
import javax.xml.datatype.DatatypeConfigurationException;
4142
import javax.xml.datatype.DatatypeFactory;
4243

@@ -60,6 +61,7 @@
6061
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithEnum;
6162
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithEnumHavingNestedEntities;
6263
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithExtendedEnumsWithNotInPayloadProperty;
64+
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithFixedPointConstraint;
6365
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithGTypeForRangeConstraints;
6466
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithGenericNumericProperty;
6567
import org.eclipse.esmf.aspectmodel.generator.json.testclasses.AspectWithMultiLanguageText;
@@ -705,6 +707,14 @@ void testGenerateJsonForAspectWithComplexSet() throws IOException {
705707
assertThat( id1 ).isNotEqualTo( id2 );
706708
}
707709

710+
@Test
711+
void testGenerateJsonForAspectWithFixedPointConstraint() throws IOException {
712+
final String generatedJson = generateJsonForModel( TestAspect.ASPECT_WITH_FIXED_POINT_CONSTRAINT );
713+
final AspectWithFixedPointConstraint aspectWithConstraint = parseJson( generatedJson, AspectWithFixedPointConstraint.class );
714+
assertThat( generatedJson ).contains( "testProperty" );
715+
assertThat( aspectWithConstraint.getTestProperty() ).matches( "\\s*\\d{3}\\.\\d{4,5}" );
716+
}
717+
708718
private String generateJsonForModel( final TestAspect testAspect ) {
709719
final Aspect aspect = TestResources.load( testAspect ).aspect();
710720
final AspectModelJsonPayloadGenerator jsonGenerator = new AspectModelJsonPayloadGenerator( aspect );
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2025 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for additional
5+
* information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
package org.eclipse.esmf.aspectmodel.generator.json.testclasses;
14+
15+
import java.util.Objects;
16+
17+
import com.fasterxml.jackson.annotation.JsonCreator;
18+
import com.fasterxml.jackson.annotation.JsonProperty;
19+
import jakarta.validation.constraints.NotNull;
20+
21+
/* Generated class for AspectWithFixedPointConstraint. */
22+
public class AspectWithFixedPointConstraint {
23+
24+
@NotNull
25+
private String testProperty;
26+
27+
@JsonCreator
28+
public AspectWithFixedPointConstraint(
29+
@JsonProperty( value = "testProperty" ) String testProperty ) {
30+
this.testProperty = testProperty;
31+
}
32+
33+
/**
34+
* Returns Test Integer Property
35+
*
36+
* @return {@link #testProperty}
37+
*/
38+
public String getTestProperty() {
39+
return this.testProperty;
40+
}
41+
42+
@Override
43+
public boolean equals( final Object o ) {
44+
if ( this == o ) {
45+
return true;
46+
}
47+
if ( o == null || getClass() != o.getClass() ) {
48+
return false;
49+
}
50+
final AspectWithFixedPointConstraint that =
51+
(AspectWithFixedPointConstraint) o;
52+
return Objects.equals( testProperty, that.testProperty );
53+
}
54+
}

0 commit comments

Comments
 (0)