/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.dmn.core; import org.junit.Ignore; import org.junit.Test; import org.kie.dmn.api.core.DMNContext; import org.kie.dmn.api.core.DMNMessage; import org.kie.dmn.api.core.DMNMessageType; import org.kie.dmn.api.core.DMNModel; import org.kie.dmn.api.core.DMNResult; import org.kie.dmn.api.core.DMNRuntime; import org.kie.dmn.api.core.DMNUnaryTest; import org.kie.dmn.api.core.ast.InputDataNode; import org.kie.dmn.api.core.event.AfterEvaluateDecisionEvent; import org.kie.dmn.api.core.event.AfterEvaluateDecisionTableEvent; import org.kie.dmn.api.core.event.BeforeEvaluateDecisionEvent; import org.kie.dmn.api.core.event.BeforeEvaluateDecisionTableEvent; import org.kie.dmn.api.core.event.DMNRuntimeEventListener; import org.kie.dmn.core.api.*; import org.kie.dmn.core.api.event.*; import org.kie.dmn.core.impl.BaseDMNTypeImpl; import org.kie.dmn.core.util.DMNRuntimeUtil; import org.kie.dmn.feel.lang.types.BuiltInType; import org.kie.dmn.model.v1_1.ItemDefinition; import org.mockito.ArgumentCaptor; import java.math.BigDecimal; import java.time.*; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.kie.dmn.core.util.DynamicTypeUtils.*; public class DMNRuntimeTest { @Test public void testSimpleItemDefinition() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "simple-item-def.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn/itemdef", "simple-item-def" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "Monthly Salary", 1000 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Yearly Salary" ), is( new BigDecimal( "12000" ) ) ); } @Test public void testCompositeItemDefinition() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0008-LX-arithmetic.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "0008-LX-arithmetic" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); Map loan = new HashMap(); loan.put( "principal", 600000 ); loan.put( "rate", 0.0375 ); loan.put( "termMonths", 360 ); context.set( "loan", loan ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "payment" ), is( new BigDecimal( "2778.693549432766720839844710324306" ) ) ); } @Test public void testTrisotechNamespace() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "trisotech_namespace.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_b8feec86-dadf-4051-9feb-8e6093bbb530", "Solution 3" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "IsDoubleHulled", true ); context.set( "Residual Cargo Size", new BigDecimal( 0.1 ) ); context.set( "Ship Size", new BigDecimal( 50 ) ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Ship can enter a Dutch port" ), is( true ) ); } @Test public void testEmptyDecision1() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "empty_decision.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_ba9fc4b1-5ced-4d00-9b61-290de4bf3213", "Solution 3" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); Map shipInfo = new HashMap(); shipInfo.put( "Size", BigDecimal.valueOf( 70 ) ); shipInfo.put( "Is Double Hulled", Boolean.FALSE ); shipInfo.put( "Residual Cargo Size", BigDecimal.valueOf( 0.1 ) ); context.set( "Ship Info", shipInfo ); // Test that even if one decision is empty or missing input data, // the other decisions in the model are still evaluated DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( dmnResult.hasErrors(), is( true ) ); assertThat( result.get( "Ship Can Enter v2" ), is( true ) ); } @Test public void testEmptyDecision2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "empty_decision.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_ba9fc4b1-5ced-4d00-9b61-290de4bf3213", "Solution 3" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); Map shipInfo = new HashMap(); shipInfo.put( "Size", BigDecimal.valueOf( 70 ) ); shipInfo.put( "Is Double Hulled", Boolean.FALSE ); shipInfo.put( "Residual Cargo Size", BigDecimal.valueOf( 0.1 ) ); context.set( "Ship Info", shipInfo ); context.set( "Ship Size", BigDecimal.valueOf( 70 ) ); context.set( "IsDoubleHulled", Boolean.FALSE ); context.set( "Residual Cargo Size", BigDecimal.valueOf( 0.1 ) ); // check that if all the input data is available, but the // decision expression is empty, the model returns a warning DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); List<DMNMessage> messages = dmnResult.getMessages( DMNMessage.Severity.WARN ); assertThat( messages.size(), is( 1 ) ); assertThat( messages.get( 0 ).getSeverity(), is( DMNMessage.Severity.WARN ) ); assertThat( messages.get( 0 ).getSourceId(), is( "_42806504-8ed5-488f-b274-de98c1bc67b9" ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Ship Can Enter v2" ), is( true ) ); } @Test public void testEventListeners() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "car_damage_responsibility.dmn", this.getClass() ); DMNRuntimeEventListener listener = mock( DMNRuntimeEventListener.class ); runtime.addListener( listener ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_820611e9-c21c-47cd-8e52-5cba2be9f9cc", "Car Damage Responsibility" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "Membership Level", "Silver" ); context.set( "Damage Types", "Body" ); context.set( "Responsible", "Driver" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); ArgumentCaptor<AfterEvaluateDecisionTableEvent> argument = ArgumentCaptor.forClass( AfterEvaluateDecisionTableEvent.class ); verify( listener, times( 2 ) ) .beforeEvaluateDecision( any( BeforeEvaluateDecisionEvent.class ) ); verify( listener, times( 2 ) ) .afterEvaluateDecision( any( AfterEvaluateDecisionEvent.class ) ); verify( listener, times( 2 ) ) .beforeEvaluateDecisionTable( any( BeforeEvaluateDecisionTableEvent.class ) ); verify( listener, times( 2 ) ) .afterEvaluateDecisionTable( argument.capture() ); AfterEvaluateDecisionTableEvent dte = argument.getAllValues().get( 0 ); assertThat( dte.getDecisionTableName(), is( "Car Damage Responsibility" ) ); assertThat( dte.getMatches(), is( Arrays.asList( 5 ) ) ); // rows are 1-based dte = argument.getAllValues().get( 1 ); assertThat( dte.getDecisionTableName(), is( "Payment method" ) ); assertThat( dte.getMatches(), is( Arrays.asList( 3 ) ) ); // rows are 1-based assertThat( dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( (Map<String, Object>) result.get( "Car Damage Responsibility" ), hasEntry( is( "EU Rent" ), is( BigDecimal.valueOf( 40 ) ) ) ); assertThat( (Map<String, Object>) result.get( "Car Damage Responsibility" ), hasEntry( is( "Renter" ), is( BigDecimal.valueOf( 60 ) ) ) ); assertThat( result.get( "Payment method" ), is( "Check" ) ); } @Test public void testErrorMessages() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "car_damage_responsibility2.dmn", this.getClass() ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_dcc63ab0-3a53-4628-8bee-3ae1f1ad683b", "Car Damage Responsibility" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.hasErrors(), is( true ) ); } @Test public void testOutputReuse() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Input_reuse_in_output.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_098bb607-eff7-4772-83ac-6ded8b371fa7", "Input reuse in output" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "Age", 40 ); context.set( "Requested Product", "Fixed30" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "My Decision" ), is( "Fixed30" ) ); } @Test public void testSimpleNot() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Simple_Not.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_98436ebb-7c42-48c0-8d11-d693e2a817c9", "Simple Not" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "Occupation", "Student" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "a" ), is( "Is Student" ) ); } @Test public void testSimpleNot2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Simple_Not.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_98436ebb-7c42-48c0-8d11-d693e2a817c9", "Simple Not" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "Occupation", "Engineer" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "a" ), is( "Is not a Student" ) ); } @Test public void testDinner() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Dinner.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_0c45df24-0d57-4acc-b296-b4cba8b71a36", "Dinner" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "Guests with children", true ); context.set( "Season", "Fall" ); context.set( "Number of guests", 4 ); context.set( "Temp", 25 ); context.set( "Rain Probability", 30 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( dmnResult.getContext().get( "Where to eat" ), is( "Outside" ) ); assertThat( dmnResult.getContext().get( "Dish" ), is( "Spareribs" ) ); assertThat( dmnResult.getContext().get( "Drinks" ), is( Arrays.asList( "Apero", "Ale", "Juice Boxes" ) ) ); } @Test public void testNotificationsApproved2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "NotificationsTest2.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "building-structure-rules" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "existingActivityApplicability", true ); context.set( "Distance", new BigDecimal( 9999 ) ); context.set( "willIncreaseTraffic", true ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Notification Status" ), is( "Notification to Province Approved" ) ); assertThat( result.get( "Permit Status" ), is( "Building Activity Province Permit Required" ) ); } @Test public void testBoxedContext() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "BoxedContext.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_0de36357-fec0-4b4e-b7f1-382d381e06e9", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ) , dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "a", 10 ); context.set( "b", 5 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); assertThat( (Map<String, Object>) dmnResult.getContext().get( "Math" ), hasEntry( "Sum", BigDecimal.valueOf( 15 ) ) ); assertThat( (Map<String, Object>) dmnResult.getContext().get( "Math" ), hasEntry( "Product", BigDecimal.valueOf( 50 ) ) ); } @Test public void testFunctionDefAndInvocation() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "FunctionDefinition.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_0de36357-fec0-4b4e-b7f1-382d381e06e9", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.getMessages().toString(), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "a", 10 ); context.set( "b", 5 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( (Map<String, Object>) dmnResult.getContext().get( "Math" ), hasEntry( "Sum", BigDecimal.valueOf( 15 ) ) ); } @Test public void testBKMNode() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0009-invocation-arithmetic.dmn", getClass() ); // runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_cb28c255-91cd-4c01-ac7b-1a9cb1ecdb11", "literal invocation1" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.getMessages().toString(), dmnModel.hasErrors(), is( false ) ); Map<String, Object> loan = new HashMap<>(); loan.put( "amount", BigDecimal.valueOf( 600000 ) ); loan.put( "rate", new BigDecimal( "0.0375" ) ); loan.put( "term", BigDecimal.valueOf( 360 ) ); DMNContext context = DMNFactory.newContext(); context.set( "fee", 100 ); context.set( "Loan", loan ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( ((BigDecimal) dmnResult.getContext().get( "MonthlyPayment" )).setScale( 8, BigDecimal.ROUND_DOWN ), is( new BigDecimal( "2878.69354943277" ).setScale( 8, BigDecimal.ROUND_DOWN ) ) ); } @Test public void testItemDefCollection() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0001-filter.dmn", getClass() ); // runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_f52ca843-504b-4c3b-a6bc-4d377bffef7a", "filter01" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.getMessages().toString(), dmnModel.hasErrors(), is( false ) ); Object[][] data = new Object[][]{ {1, "Finances", "John"}, {2, "Engineering", "Mary"}, {3, "Sales", "Kevin"} }; List<Map<String, Object>> employees = new ArrayList<>(); for ( int i = 0; i < data.length; i++ ) { Map<String, Object> e = new HashMap<>(); e.put( "id", data[i][0] ); e.put( "dept", data[i][1] ); e.put( "name", data[i][2] ); employees.add( e ); } DMNContext context = DMNFactory.newContext(); context.set( "Employee", employees ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( dmnResult.getContext().get( "filter01" ), is( Arrays.asList( "Mary" ) ) ); } @Test public void testList() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "list-expression.dmn", getClass() ); // runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "list-expression" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.getMessages().toString(), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( dmnResult.getContext().get( "Name list" ), is( Arrays.asList( "John", "Mary" ) ) ); } @Test public void testRelation() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "relation-expression.dmn", getClass() ); // runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "relation-expression" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.getMessages().toString(), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); assertThat( dmnResult.getContext().get( "Employee Relation" ), is( instanceOf( List.class ) ) ); List<Map<String, Object>> employees = (List<Map<String, Object>>) dmnResult.getContext().get( "Employee Relation" ); Map<String, Object> e = employees.get( 0 ); assertThat( e.get( "Name" ), is( "John" ) ); assertThat( e.get( "Dept" ), is( "Sales" ) ); assertThat( e.get( "Salary" ), is( BigDecimal.valueOf( 100000 ) ) ); e = employees.get( 1 ); assertThat( e.get( "Name" ), is( "Mary" ) ); assertThat( e.get( "Dept" ), is( "Finances" ) ); assertThat( e.get( "Salary" ), is( BigDecimal.valueOf( 120000 ) ) ); } @Test public void testMissingInputData() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "missing_input_data.dmn", getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_4047acf3-fce2-42f3-abf2-fb06282c1ea0", "Upgrade Based On Promotions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( true ) ); assertThat( dmnModel.getMessages().get( 0 ).getMessageType(), is( DMNMessageType.ERR_COMPILING_FEEL ) ); } @Test public void testLendingExample() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0004-lending.dmn", getClass() ); // runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_4e0f0b70-d31c-471c-bd52-5ca709ed362b", "Lending1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); Map applicant = new HashMap(); Map monthly = new HashMap(); monthly.put( "Income", 6000 ); monthly.put( "Expenses", 2000 ); monthly.put( "Repayments", 0 ); applicant.put( "Monthly", monthly ); applicant.put( "Age", 35 ); applicant.put( "ExistingCustomer", true ); applicant.put( "MaritalStatus", "M" ); applicant.put( "EmploymentStatus", "EMPLOYED" ); Map product = new HashMap(); product.put( "ProductType", "STANDARD LOAN" ); product.put( "Amount", 350000 ); product.put( "Rate", new BigDecimal( "0.0395" ) ); product.put( "Term", 360 ); Map bureau = new HashMap(); bureau.put( "CreditScore", 649 ); bureau.put( "Bankrupt", false ); context.set( "ApplicantData", applicant ); context.set( "RequestedProduct", product ); context.set( "BureauData", bureau ); context.set( "SupportingDocuments", "yes" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext ctx = dmnResult.getContext(); assertThat( ctx.get( "ApplicationRiskScore" ), is( BigDecimal.valueOf( 130 ) ) ); assertThat( ctx.get( "Pre-bureauRiskCategory" ), is( "LOW" ) ); assertThat( ctx.get( "BureauCallType" ), is( "MINI" ) ); assertThat( ctx.get( "Post-bureauRiskCategory" ), is( "LOW" ) ); assertThat( ((BigDecimal)ctx.get( "RequiredMonthlyInstallment" )).setScale( 5, BigDecimal.ROUND_DOWN ), is( new BigDecimal( "1680.880325608555" ).setScale( 5, BigDecimal.ROUND_DOWN ) ) ); assertThat( ctx.get( "Pre-bureauAffordability" ), is( true ) ); assertThat( ctx.get( "Eligibility" ), is( "ELIGIBLE" ) ); assertThat( ctx.get( "Strategy" ), is( "BUREAU" ) ); assertThat( ctx.get( "Post-bureauAffordability" ), is( true ) ); assertThat( ctx.get( "Routing" ), is( "ACCEPT" ) ); } @Test public void testDateAndTime() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0007-date-time.dmn", getClass() ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_69430b3e-17b8-430d-b760-c505bf6469f9", "dateTime Table 58" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "dateString", "2015-12-24" ); context.set( "timeString", "00:00:01-01:00" ); context.set( "dateTimeString", "2016-12-24T23:59:00-05:00" ); context.set( "Hours", 12 ); context.set( "Minutes", 59 ); context.set( "Seconds", new BigDecimal( "1.3" ) ); context.set( "Timezone", "PT-1H" ); context.set( "Year", 1999 ); context.set( "Month", 11 ); context.set( "Day", 22 ); context.set( "oneHour", Duration.parse( "PT1H" ) ); // <variable name="oneHour" typeRef="feel:days and time duration"/> context.set( "durationString", "P13DT2H14S" ); // <variable name="durationString" typeRef="feel:string"/> DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext ctx = dmnResult.getContext(); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); assertThat( ctx.get("Date-Time"), is( ZonedDateTime.of( 2016, 12, 24, 23, 59, 0, 0, ZoneOffset.ofHours( -5 ) ) ) ); assertThat( ctx.get("Date"), is( new HashMap<String, Object>( ) {{ put( "fromString", LocalDate.of( 2015, 12, 24 ) ); put( "fromDateTime", LocalDate.of( 2016, 12, 24 ) ); put( "fromYearMonthDay", LocalDate.of( 1999, 11, 22 ) ); }} ) ); assertThat( ctx.get("Time"), is( OffsetTime.of( 00, 00, 01, 00, ZoneOffset.ofHours( -1 ) ) ) ); assertThat( ctx.get("Date-Time2"), is( ZonedDateTime.of( 2015, 12, 24, 00, 00, 01, 00, ZoneOffset.ofHours( -1 ) ) ) ); assertThat( ctx.get("Time2"), is( OffsetTime.of( 00, 00, 01, 00, ZoneOffset.ofHours( -1 ) ) ) ); assertThat( ctx.get("Time3"), is( OffsetTime.of( 12, 59, 1, 300000000, ZoneOffset.ofHours( -1 ) )) ); assertThat( ctx.get("dtDuration1"), is( Duration.parse( "P13DT2H14S" ) ) ); assertThat( ctx.get("dtDuration2"), is( Duration.parse( "P367DT3H58M59S" ) ) ); assertThat( ctx.get("hoursInDuration"), is( new BigDecimal( "3" ) ) ); assertThat( ctx.get("sumDurations"), is( Duration.parse( "PT9125H59M13S" ) ) ); assertThat( ctx.get("ymDuration2"), is( Period.parse( "P1Y" ) ) ); assertThat( ctx.get("cDay"), is( BigDecimal.valueOf( 24 ) ) ); assertThat( ctx.get("cYear"), is( BigDecimal.valueOf( 2015 ) ) ); assertThat( ctx.get("cMonth"), is( BigDecimal.valueOf( 12 ) ) ); assertThat( ctx.get("cHour"), is( BigDecimal.valueOf( 0 ) ) ); assertThat( ctx.get("cMinute"), is( BigDecimal.valueOf( 0 ) ) ); assertThat( ctx.get("cSecond"), is( BigDecimal.valueOf( 1 ) ) ); assertThat( ctx.get("cTimezone"), is( Duration.parse( "PT-1H" ) ) ); assertThat( ctx.get("years"), is( BigDecimal.valueOf( 1 ) ) ); assertThat( ctx.get("seconds"), is( BigDecimal.valueOf( 14 ) ) ); } @Test public void testFiltering() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Person_filtering_by_age.dmn", getClass() ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_e215ed7a-701b-4c53-b8df-4b4d23d5fe32", "Person filtering by age" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "Min Age", 50 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), ((List)dmnResult.getContext().get("Filtering")).size(), is( 2 ) ); } @Test public void testNowFunction() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "today_function_test.dmn", getClass() ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_4ad80959-5fd8-46b7-8c9a-ab2fa58cb5b4", "When is it" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "The date", LocalDate.of( 2017, 01, 12 ) ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.getContext().get("When is it"), is( "It is in the past" ) ); } @Test public void testTimeFunction() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "TimeFromDate.dmn", getClass() ); runtime.addListener( DMNRuntimeUtil.createListener() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_ecf4ea54-2abc-4e2f-a101-4fe14e356a46", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "datetimestring", "2016-07-29T05:48:23" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.getContext().get("time"), is( LocalTime.of( 5, 48, 23 ) ) ); } @Test public void testAlternativeNSDecl() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "alternative_feel_ns_declaration.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "0001-input-data-string" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); context.set( "Full Name", "John Doe" ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.getDecisionResults().size(), is( 1 ) ); assertThat( dmnResult.getDecisionResultByName( "Greeting Message" ).getResult(), is( "Hello John Doe" ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Greeting Message" ), is( "Hello John Doe" ) ); } @Test public void testDTInContext() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "DT_in_context.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_4acdcb25-b298-435e-abd5-efd00ed686a5", "Drawing 1" ); assertThat( dmnModel, notNullValue() ); DMNContext context = DMNFactory.newContext(); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.getDecisionResults().size(), is( 1 ) ); assertThat( dmnResult.getDecisionResultByName( "D1" ).getResult(), is( instanceOf( Map.class ) ) ); DMNContext result = dmnResult.getContext(); assertThat( ((Map)result.get( "D1" )).get( "Text color" ), is( "red" ) ); } @Test public void testDTUsingEqualsUnaryTestWithVariable1() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "DT_using_variables.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_ed1ec15b-40aa-424d-b1d0-4936df80b135", "DT Using variables" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); Map<String, Object> complex = new HashMap<>( ); complex.put( "aBoolean", true ); complex.put( "aNumber", 10 ); complex.put( "aString", "bar" ); DMNContext context = DMNFactory.newContext(); context.set( "Complex", complex ); context.set( "Another boolean", true ); context.set( "Another String", "bar"); context.set( "Another number", 10 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Compare Boolean" ), is( "Same boolean" ) ); assertThat( result.get( "Compare Number" ), is( "Equals" ) ); assertThat( result.get( "Compare String" ), is( "Same String" ) ); } @Test public void testDTUsingEqualsUnaryTestWithVariable2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "DT_using_variables.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_ed1ec15b-40aa-424d-b1d0-4936df80b135", "DT Using variables" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.hasErrors(), is( false ) ); Map<String, Object> complex = new HashMap<>(); complex.put( "aBoolean", true ); complex.put( "aNumber", 10 ); complex.put( "aString", "bar" ); DMNContext context = DMNFactory.newContext(); context.set( "Complex", complex ); context.set( "Another boolean", false ); context.set( "Another String", "foo" ); context.set( "Another number", 20 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Compare Boolean" ), is( "Not same boolean" ) ); assertThat( result.get( "Compare Number" ), is( "Bigger" ) ); assertThat( result.get( "Compare String" ), is( "Different String" ) ); } @Test public void testLoanComparison() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "loanComparison.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_3a1fd8f4-ea04-4453-aa30-ff14140e3441", "loanComparison" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = DMNFactory.newContext(); context.set( "RequestedAmt", 500000 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); } @Test public void testGetViableLoanProducts() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Get_Viable_Loan_Products.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_3e1a628d-36bc-45f1-8464-b201735e5ce0", "Get Viable Loan Products" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); Map<String, Object> requested = new HashMap<>( ); requested.put( "PropertyZIP", "91001" ); requested.put( "LoanAmt", 300000 ); requested.put( "Objective", "Payment" ); requested.put( "DownPct", new BigDecimal( "0.4" ) ); requested.put( "MortgageType", "Fixed 20" ); DMNContext context = DMNFactory.newContext(); context.set( "Requested", requested ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "isConforming" ), is( true ) ); assertThat( (Collection<Object>) result.get( "LoanTypes" ), hasSize( 3 ) ); } @Test public void testYearsAndMonthsDuration() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "yearMonthDuration.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_6eda1490-21ca-441e-8a26-ab3ca800e43c", "Drawing 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); BuiltInType feelType = (BuiltInType) BuiltInType.determineTypeFromName( "yearMonthDuration" ); Period period = (Period) feelType.fromString( "P2Y1M" ); DMNContext context = runtime.newContext(); context.set( "iDuration", period ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "How long" ), is( "Longer than a year" ) ); } @Test public void testInvalidVariableNames() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "invalid-variable-names.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "0001-input-data-string" ); assertThat( dmnModel, notNullValue() ); assertThat( dmnModel.hasErrors(), is(true) ); } @Test public void testNull() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "null_values.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "Null values model" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set( "Null Input", null ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Null value" ), is( "Input is null" ) ); context = runtime.newContext(); context.set( "Null Input", "foo" ); dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); result = dmnResult.getContext(); assertThat( result.get( "Null value" ), is( "Input is not null" ) ); } @Test @Ignore public void testInvalidUHitPolicy() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Invalid_U_hit_policy.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_7cf49108-9b55-4f35-b5ef-f83448061757", "Greater than 5 - Invalid U hit policy" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set( "Number", 5 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( true ) ); assertThat( dmnResult.getMessages().size(), is( 2 ) ); assertThat( dmnResult.getMessages().get( 0 ).getSourceId(), is("_c5eda7c3-7f22-43c2-8c1e-a3cc79bb7a74" ) ); assertThat( dmnResult.getMessages().get( 1 ).getSourceId(), is("_5bac3e4c-b59a-4f14-b5cf-d4d88c60877f" ) ); } @Test public void testInvalidModel() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Loan_Prequalification_Condensed_Invalid.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_ba68fb9d-7421-4f3a-a7ab-f785ea0bae6b", "Loan Prequalification Condensed" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( true ) ); assertThat( dmnModel.getMessages().size(), is( 2 ) ); assertThat( dmnModel.getMessages().get( 0 ).getSourceId(), is( "_8b5cac9e-c8ca-4817-b05a-c70fa79a8d48" ) ); assertThat( dmnModel.getMessages().get( 1 ).getSourceId(), is( "_ef09d90e-e1a4-4ec9-885b-482d1f4a1cee" ) ); } @Test public void testNullOnNumber() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Number_and_null_entry.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_a293b9f9-c912-41ee-8147-eae59ba86ac5", "Number and null entry" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set( "num", null ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Decision Logic 1" ), is( "Null" ) ); context = runtime.newContext(); context.set( "num", 4 ); dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); result = dmnResult.getContext(); assertThat( result.get( "Decision Logic 1" ), is( "Positive number" ) ); } @Test public void testLoan_Recommendation2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Loan_Recommendation2.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_35c7339b-b868-43da-8f06-eb481708c73c", "Loan Recommendation2" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); Map<String,Object> loan = new HashMap<>( ); loan.put( "Amount", 100000); loan.put( "Rate", 2.39); loan.put( "Term", 60); Map<String,Object> borrower = new HashMap<>( ); borrower.put( "Age", 39); borrower.put( "EmploymentStatus", "Employed"); borrower.put( "YearsAtCurrentEmployer", 10); borrower.put( "TotalAnnualIncome", 150000); borrower.put( "NonSalaryIncome", 0); borrower.put( "MonthlyDebtPmtAmt", 2000); borrower.put( "LiquidAssetsAmt", 50000); DMNContext context = runtime.newContext(); context.set( "Credit Score", null ); context.set( "Appraised Value", 200000 ); context.set( "Loan", loan ); context.set( "Borrower", borrower ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Loan Recommendation" ), is( "Decline" ) ); } @Test public void testInputClauseTypeRefWithAllowedValues() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "actualInputMatchInputValues-forTypeRef.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://www.drools.org/kie-dmn/definitions", "definitions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("MyInput", "a"); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "MyDecision" ), is( "Decision taken" ) ); } @Test public void testInputDataTypeRefWithAllowedValues() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "actualInputMatchInputValues-forTypeRef.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://www.drools.org/kie-dmn/definitions", "definitions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("MyInput", "zzz"); // <<< `zzz` is NOT in the list of allowed value as declared by the typeRef for this inputdata DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( true ) ); assertThat( dmnResult.getMessages().size(), is( 1 ) ); assertThat( dmnResult.getMessages().get( 0 ).getSourceId(), is( "_3d560678-a126-4654-a686-bc6d941fe40b" ) ); } @Test public void testPriority_table() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "priority_table.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_ff54a44d-b8f5-48fc-b2b7-43db767e8a1c", "not quite all or nothing P" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("isAffordable", false); context.set("RiskCategory", "Medium"); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Approval Status" ), is( "Declined" ) ); } @Test public void testPriority_table_context_recursion() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "priority_table_context_recursion.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_ff54a44d-b8f5-48fc-b2b7-43db767e8a1c", "not quite all or nothing P" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("isAffordable", false); context.set("RiskCategory", "Medium"); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Approval Status" ), is( "Declined" ) ); } @Test public void testPriority_table_missing_output_values() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "DTABLE_PRIORITY_MISSING_OUTVALS.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "DTABLE_PRIORITY_MISSING_OUTVALS" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( true ) ); assertThat( dmnModel.getMessages().size(), is( 1 ) ); assertThat( dmnModel.getMessages().get( 0 ).getSourceId(), is( "_oApprovalStatus" ) ); } @Test public void testDTInputExpressionLocalXmlnsInference() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "drools1502-InputExpression.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://www.drools.org/kie-dmn/definitions", "definitions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("MyInput", "a"); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "MyDecision" ), is( "Decision taken" ) ); } @Test public void testNoPrefix() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "drools1502-noprefix.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://www.drools.org/kie-dmn/definitions", "definitions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); context.set("MyInput", "a"); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "MyDecision" ), is( "Decision taken" ) ); } @Test public void testWrongConstraintsInItemDefinition() { // DROOLS-1503 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "WrongConstraintsInItemDefinition.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_81d8fefe-9cd7-43b8-922a-ff245c434457", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( true ) ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.getMessages().size(), is( 3 ) ); assertThat( dmnModel.getMessages().get( 0 ).getSourceReference(), is( instanceOf( ItemDefinition.class ) ) ); assertThat( dmnModel.getMessages().get( 0 ).getMessageType(), is( DMNMessageType.ERR_COMPILING_FEEL ) ); assertThat( dmnModel.getMessages().get( 1 ).getSourceId(), is( "_e794c655-4fdf-45d1-b7b7-d990df513f92" ) ); assertThat( dmnModel.getMessages().get( 1 ).getMessageType(), is( DMNMessageType.ERR_COMPILING_FEEL ) ); // The DecisionTable does not define typeRef for the single OutputClause, but neither the enclosing Decision define typeRef for its variable assertThat( dmnModel.getMessages().get( 2 ).getSourceId(), is( "_31911de7-e184-411c-99d1-f33977971270" ) ); assertThat( dmnModel.getMessages().get( 2 ).getMessageType(), is( DMNMessageType.MISSING_TYPE_REF ) ); } @Test public void testResolutionOfVariableWithLeadingOrTrailingSpaces() { // DROOLS-1504 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "variableLeadingTrailingSpaces.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://www.drools.org/kie-dmn/definitions", "definitions" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); Map<String, String> person = new HashMap<>(); person.put("Name", "John"); person.put("Surname", "Doe"); context.set("Input Person", person); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Further Decision" ), is( "The person was greeted with: 'Ciao John Doe'" ) ); } @Test public void testOutOfOrderItemsNPE() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "out-of-order-items.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "out-of-order" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.FAILED_VALIDATOR ) ), is( false ) ); } @Test public void testItemDefDependencies() { // DROOLS-1505 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "itemDef-dependency.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_2374ee6d-75ed-4e9d-95d3-a88c135e1c43", "Drawing 1a" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); Map<String, String> person = new HashMap<>(); person.put( "Full Name", "John Doe" ); person.put( "Address", "100 East Davie Street" ); context.set( "Input Person", person ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "My Decision" ), is( "The person John Doe is located at 100 East Davie Street" ) ); } @Test public void testDecisionResultTypeCheck() { // DROOLS-1513 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "LoanRecommendationWrongOutputType.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_591d49d0-26e1-4a1c-9f72-b65bec09964a", "Loan Recommendation Multi-step" ); assertThat( dmnModel, notNullValue() ); System.out.println(formatMessages( dmnModel.getMessages() )); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); Map<String, Number> loan = new HashMap<>(); loan.put("Amount", 100); loan.put("Rate", 12); loan.put("Term", 1); context.set("Loan", loan); DMNResult dmnResult = runtime.evaluateDecisionByName( dmnModel, "Loan Payment", context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( true ) ); assertThat( dmnResult.getMessages().size(), is( 1 ) ); assertThat( dmnResult.getMessages().get( 0 ).getSourceId(), is("_93062144-ebc7-4ef7-a156-c342aeffac49") ); assertThat( dmnResult.getMessages().get( 0 ).getMessageType(), is( DMNMessageType.ERROR_EVAL_NODE ) ); } @Test public void testNPE() { // DROOLS-1512 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "NPE.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_95b7ee22-1964-4be5-b7db-7db66692c707", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext context = runtime.newContext(); DMNResult dmnResult = runtime.evaluateAll( dmnModel, context ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( true ) ); assertThat( dmnResult.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.REQ_NOT_FOUND ) ), is( true ) ); } @Test public void testAllowedValuesChecks() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "AllowedValuesChecks.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_238bd96d-47cd-4746-831b-504f3e77b442", "AllowedValuesChecks" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx1 = runtime.newContext(); ctx1.set("p1", prototype(entry("Name", "P1"), entry("Interests", Arrays.asList(new String[]{"Golf"})))); DMNResult dmnResult1 = runtime.evaluateAll( dmnModel, ctx1 ); assertThat( formatMessages( dmnResult1.getMessages() ), dmnResult1.hasErrors(), is( false ) ); assertThat( dmnResult1.getContext().get( "MyDecision" ), is( "The Person P1 likes 1 thing(s)." ) ); DMNContext ctx2 = runtime.newContext(); ctx2.set("p1", prototype(entry("Name", "P2"), entry("Interests", Arrays.asList(new String[]{"x"})))); DMNResult dmnResult2 = runtime.evaluateAll( dmnModel, ctx2 ); assertThat( formatMessages( dmnResult2.getMessages() ), dmnResult2.hasErrors(), is( true ) ); assertThat( dmnResult2.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.ERROR_EVAL_NODE ) ), is( true ) ); DMNContext ctx3 = runtime.newContext(); ctx3.set("p1", prototype(entry("Name", "P3"), entry("Interests", Arrays.asList(new String[]{"Golf", "Computer"})))); DMNResult dmnResult3 = runtime.evaluateAll( dmnModel, ctx3 ); assertThat( formatMessages( dmnResult3.getMessages() ), dmnResult3.hasErrors(), is( false ) ); assertThat( dmnResult3.getContext().get( "MyDecision" ), is( "The Person P3 likes 2 thing(s)." ) ); DMNContext ctx4 = runtime.newContext(); ctx4.set("p1", prototype(entry("Name", "P4"), entry("Interests", Arrays.asList(new String[]{"Golf", "x"})))); DMNResult dmnResult4 = runtime.evaluateAll( dmnModel, ctx4 ); assertThat( formatMessages( dmnResult4.getMessages() ), dmnResult4.hasErrors(), is( true ) ); assertThat( dmnResult4.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.ERROR_EVAL_NODE ) ), is( true ) ); } @Test public void testUnionofLetters() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Union_of_letters.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_76362694-41e8-400c-8dea-e5f033d4f405", "Union of letters" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx1 = runtime.newContext(); ctx1.set("A1", Arrays.asList(new String[]{"a", "b"})); ctx1.set("A2", Arrays.asList(new String[]{"b", "c"})); DMNResult dmnResult1 = runtime.evaluateAll( dmnModel, ctx1 ); assertThat( formatMessages( dmnResult1.getMessages() ), dmnResult1.hasErrors(), is( false ) ); assertThat( (List<?>) dmnResult1.getContext().get( "D1" ), contains( "a", "b", "c" ) ); DMNContext ctx2 = runtime.newContext(); ctx2.set("A1", Arrays.asList(new String[]{"a", "b"})); ctx2.set("A2", Arrays.asList(new String[]{"b", "x"})); DMNResult dmnResult2 = runtime.evaluateAll( dmnModel, ctx2 ); assertThat( formatMessages( dmnResult2.getMessages() ), dmnResult2.hasErrors(), is( true ) ); assertThat( dmnResult2.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.ERROR_EVAL_NODE ) ), is( true ) ); } @Test public void testUnknownVariable1() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "unknown_variable1.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_9105d4a6-6049-4ace-a9cd-88f18d29bc8f", "Loan Recommendation - context" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.getMessages().size(), is( 2 ) ); assertEquals(1, dmnModel.getMessages().stream().filter( m -> m.getMessageType().equals(DMNMessageType.ERR_COMPILING_FEEL) ) .filter( m -> m.getMessage().contains("Unknown variable 'NonSalaryPct'") ) .count()); } @Test public void testUnknownVariable2() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "unknown_variable2.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_9105d4a6-6049-4ace-a9cd-88f18d29bc8f", "Loan Recommendation - context" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.getMessages().size(), is( 1 ) ); assertThat( dmnModel.getMessages().get( 0 ).getMessageType(), is( DMNMessageType.ERR_COMPILING_FEEL ) ); assertThat( dmnModel.getMessages().get( 0 ).getMessage(), containsString( "Unknown variable 'Borrower.liquidAssetsAmt'" ) ); } @Test public void testSingleDecisionWithContext() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "SingleDecisionWithContext.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_71af58db-e1df-4b0f-aee2-48e0e8d89672", "SingleDecisionWithContext" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext emptyContext = runtime.newContext(); DMNResult dmnResult = runtime.evaluateAll( dmnModel, emptyContext ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "MyDecision" ), is( "Hello John Doe" ) ); } @Test public void testEx_6_1() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "Ex_6_1.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_5f1269c8-1e6f-4748-9eca-26aa1b1278ef", "Ex 6-1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx = runtime.newContext(); Map<String, Object> t1 = new HashMap<>(); t1.put("city", "Los Angeles"); t1.put("name", "Los Angeles"); t1.put("wins", 0); t1.put("losses", 1); t1.put("bonus points", 40); Map<String, Object> t2 = new HashMap<>(); t2.put("city", "San Francisco"); t2.put("name", "San Francisco"); t2.put("wins", 1); t2.put("losses", 0); t2.put("bonus points", 7); ctx.set("NBA Pacific", Arrays.asList(new Map[]{t1, t2})); DMNResult dmnResult = runtime.evaluateAll( dmnModel, ctx ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get( "Number of distinct cities" ), is( new BigDecimal(2) ) ); assertThat( result.get( "Second place losses" ), is( new BigDecimal(0) ) ); assertThat( result.get( "Max wins" ), is( new BigDecimal(1) ) ); assertThat( result.get( "Mean wins" ), is( new BigDecimal(0.5) ) ); assertThat( (List<?>) result.get( "Positions of Los Angeles teams" ), contains( new BigDecimal(1) ) ); assertThat( result.get( "Number of teams" ), is( new BigDecimal(2) ) ); assertThat( result.get( "Sum of bonus points" ), is( new BigDecimal(47) ) ); } @Test public void testSingletonlist_function_call() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "singletonlist_fuction_call.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_0768879b-5ee1-410f-92f0-7732573b069d", "expression function subst [a] with a" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx = runtime.newContext(); ctx.set("InputLineItem", prototype(entry("Line", "0015"), entry("Description", "additional Battery"))); DMNResult dmnResult = runtime.evaluateAll( dmnModel, ctx ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get("The Battery"), is( prototype(entry("Line", "0010"), entry("Description", "Battery")) ) ); assertThat( (List<?>)result.get("Remove Battery"), contains( prototype(entry("Line", "0020"), entry("Description", "Case")), prototype(entry("Line", "0030"), entry("Description", "Power Supply")) ) ); assertThat( (List<?>)result.get("Remove Battery"), not( contains( prototype(entry("Line", "0010"), entry("Description", "Battery")) ) ) ); assertThat( (List<?>)result.get("Insert before Line 0020"), contains( prototype(entry("Line", "0010"), entry("Description", "Battery")), prototype(entry("Line", "0015"), entry("Description", "additional Battery")), prototype(entry("Line", "0020"), entry("Description", "Case")), prototype(entry("Line", "0030"), entry("Description", "Power Supply")) ) ); } @Test public void testJavaFunctionContext() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "java_function_context.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_b42317c4-4f0c-474e-a0bf-2895b0b3c314", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx = runtime.newContext(); ctx.set( "Input", 3.14 ); DMNResult dmnResult = runtime.evaluateAll( dmnModel, ctx ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( ((BigDecimal) result.get( "D1" )).setScale( 4, BigDecimal.ROUND_HALF_UP ), is( new BigDecimal( "-1.0000" ) ) ); assertThat( ((BigDecimal) result.get( "D2" )).setScale( 4, BigDecimal.ROUND_HALF_UP ), is( new BigDecimal( "-1.0000" ) ) ); } @Test public void testPMMLFunctionContext() { DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "pmml_function_context.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/dmn/definitions/_b42317c4-4f0c-474e-a0bf-2895b0b3c314", "Dessin 1" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); assertThat( dmnModel.getMessages().size(), is( 1 ) ); assertThat( dmnModel.getMessages().get( 0 ).getMessageType(), is( DMNMessageType.INVALID_ATTRIBUTE_VALUE ) ); assertThat( dmnModel.getMessages().get( 0 ).getSeverity(), is( DMNMessage.Severity.WARN ) ); } @Test public void test_countCSATradeRatings() { // DROOLS-1563 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "countCSATradeRatings.dmn", this.getClass() ); DMNModel dmnModel = runtime.getModel( "http://www.trisotech.com/definitions/_1a7d184c-2e38-4462-ae28-15591ef6d534", "countCSATradeRatings" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); DMNContext ctx = runtime.newContext(); List<Map<?, ?>> ratings = new ArrayList<>(); ratings.add( prototype(entry("Agency", "FITCH"), entry("Value", "val1")) ); ratings.add( prototype(entry("Agency", "MOODY"), entry("Value", "val2")) ); ctx.set("CSA Trade Ratings", ratings); DMNResult dmnResult = runtime.evaluateAll( dmnModel, ctx ); assertThat( formatMessages( dmnResult.getMessages() ), dmnResult.hasErrors(), is( false ) ); DMNContext result = dmnResult.getContext(); assertThat( result.get("Trade Ratings"), is( new BigDecimal(2) ) ); DMNContext ctx2 = runtime.newContext(); ctx2.set("CSA Trade Ratings", null); DMNResult dmnResult2 = runtime.evaluateAll( dmnModel, ctx2 ); assertThat( formatMessages( dmnResult2.getMessages() ), dmnResult2.hasErrors(), is( false ) ); DMNContext result2 = dmnResult2.getContext(); assertThat( result2.get("Trade Ratings"), nullValue() ); DMNResult dmnResult3 = runtime.evaluateAll( dmnModel, runtime.newContext() ); assertThat( formatMessages( dmnResult3.getMessages() ), dmnResult3.hasErrors(), is( true ) ); assertThat( dmnResult3.getMessages().stream().anyMatch( m -> m.getMessageType().equals( DMNMessageType.REQ_NOT_FOUND ) ), is( true ) ); } @Test public void testDMNInputDataNodeTypeTest() { // DROOLS-1569 DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "DMNInputDataNodeTypeTest.dmn", this.getClass() ); final String MODEL_NAMESPACE = "http://www.trisotech.com/definitions/_17396034-163a-48aa-9a7f-c6eb17f9cc6c"; final String FEEL_NAMESPACE = "http://www.omg.org/spec/FEEL/20140401"; DMNModel dmnModel = runtime.getModel( MODEL_NAMESPACE, "DMNInputDataNodeTypeTest" ); assertThat( dmnModel, notNullValue() ); assertThat( formatMessages( dmnModel.getMessages() ), dmnModel.hasErrors(), is( false ) ); InputDataNode idnMembership = dmnModel.getInputs().stream().filter(idn -> idn.getName().equals("Membership Level")).findFirst().get(); assertThat( idnMembership.getType().getBaseType().getNamespace(), is(FEEL_NAMESPACE)); assertThat( idnMembership.getType().getBaseType().getName(), is("string")); assertThat( idnMembership.getType().isCollection(), is(false)); assertThat( idnMembership.getType().isComposite(), is(false)); assertThat( idnMembership.getType().getAllowedValues().size(), is( 3 ) ); assertThat( idnMembership.getType().getAllowedValues().get(0).toString(), is( "\"Gold\"" )); assertThat( idnMembership.getType().getAllowedValues().get(1).toString(), is( "\"Silver\"" )); assertThat( idnMembership.getType().getAllowedValues().get(2).toString(), is( "\"None\"" )); InputDataNode idnMembershipLevels = dmnModel.getInputs().stream().filter(idn -> idn.getName().equals("Membership Levels")).findFirst().get(); assertThat( idnMembershipLevels.getType().getBaseType().getNamespace(), is(MODEL_NAMESPACE)); assertThat( idnMembershipLevels.getType().getBaseType().getName(), is("tMembershipLevel")); assertThat( idnMembershipLevels.getType().isCollection(), is(true)); assertThat( idnMembershipLevels.getType().isComposite(), is(false)); assertThat( idnMembershipLevels.getType().getAllowedValues().isEmpty(), is( true )); InputDataNode idnPercent = dmnModel.getInputs().stream().filter(idn -> idn.getName().equals("Percent")).findFirst().get(); assertThat( idnPercent.getType().getBaseType().getNamespace(), is(FEEL_NAMESPACE)); assertThat( idnPercent.getType().getBaseType().getName(), is("number")); assertThat( idnPercent.getType().isCollection(), is(false)); assertThat( idnPercent.getType().isComposite(), is(false)); assertThat( idnPercent.getType().getAllowedValues().size(), is( 1 ) ); assertThat( idnPercent.getType().getAllowedValues().get(0).toString(), is( "[0..100]" )); InputDataNode idnCarDamageResponsibility = dmnModel.getInputs().stream().filter(idn -> idn.getName().equals("Car Damage Responsibility")).findFirst().get(); assertThat( idnCarDamageResponsibility.getType().getBaseType(), is( nullValue() )); assertThat( idnCarDamageResponsibility.getType().isCollection(), is(false)); assertThat( idnCarDamageResponsibility.getType().isComposite(), is(true)); } private String formatMessages(List<DMNMessage> messages) { return messages.stream().map( m -> m.toString() ).collect( Collectors.joining( "\n" ) ); } }