All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kie.dmn.validation.DMNv1x.dmn-validation-rules.drl Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.validation.DMNv1x;

import org.kie.dmn.model.api.*;
import org.kie.dmn.api.core.DMNMessage;
import org.kie.dmn.core.impl.DMNMessageImpl;
import org.kie.dmn.core.util.MsgUtil;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.parser.feel11.FEELParser;
import org.kie.dmn.feel.runtime.events.SyntaxErrorEvent;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.core.util.Msg;
import org.kie.dmn.core.compiler.ImportDMNResolverUtil;
import org.kie.dmn.validation.ValidatorUtil;

import function org.kie.dmn.validation.ValidatorUtil.rightOfHash;
import function org.kie.dmn.validation.ValidatorUtil.getRootItemDef;

global org.kie.dmn.validation.MessageReporter reporter;

declare entry-point "DMNImports" end

rule MISSING_IMPORT_p1
when
  $elemRef : Import( ImportDMNResolverUtil.whichImportType(this) == ImportDMNResolverUtil.ImportType.DMN,
                     $importedNS : namespace,
                     getAdditionalAttributes().get(ValidatorUtil.KIE_MODEL_NAME_QNAME) == null )
  not( Definitions( namespace == $importedNS ) from entry-point "DMNImports" )
then
  reporter.report(DMNMessage.Severity.ERROR, $elemRef, Msg.IMPORT_NOT_FOUND_FOR_NODE, $importedNS, $elemRef.getIdentifierString());
end

rule MISSING_IMPORT_p2
when
  $elemRef : Import( ImportDMNResolverUtil.whichImportType(this) == ImportDMNResolverUtil.ImportType.DMN,
                     $importedNS : namespace,
                     getAdditionalAttributes().get(ValidatorUtil.KIE_MODEL_NAME_QNAME) != null,
                     $importedName : getAdditionalAttributes().get(ValidatorUtil.KIE_MODEL_NAME_QNAME) )
  not( Definitions( namespace == $importedNS, name == $importedName ) from entry-point "DMNImports" )
then
  reporter.report(DMNMessage.Severity.ERROR, $elemRef, Msg.IMPORT_NOT_FOUND_FOR_NODE, $importedNS + $importedName, $elemRef.getIdentifierString());
end

rule INVOCATION_MISSING_EXPR
when
    $b : Binding( expression == null )
then
    reporter.report( DMNMessage.Severity.WARN, $b, Msg.MISSING_EXPRESSION_FOR_PARAM_OF_INVOCATION,
                     $b.getParameter() != null ? $b.getParameter().getIdentifierString() : "[unnamed]",
                     $b.getParentDRDElement().getIdentifierString() );
end

rule NAME_EMPTY
when
    $ne : NamedElement( !(this instanceof Import),
                        !FEELParser.isVariableNameEmpty( name ) )
then
    java.util.List errors = FEELParser.checkVariableNameEmpty( $ne.getName() );
    if ( ! errors.isEmpty() ) {
        reporter.report( DMNMessage.Severity.ERROR,  $ne , Msg.INVALID_NAME, $ne.getName(), errors.get( 0 ).getMessage() );
    }
end

rule NAME_INVALID
when
    $ne : NamedElement( parent != null,
                        // the following constraint prevents duplicate reporting due to variables having the same name as their enclosing nodes
                        !( parent instanceof NamedElement ) || (((NamedElement)parent).name != name ),
                        !FEELParser.isVariableNameValid( name ) )
then
    java.util.List errors = FEELParser.checkVariableName( $ne.getName() );
    if ( ! errors.isEmpty() ) {
        reporter.report( DMNMessage.Severity.ERROR,  $ne , Msg.INVALID_NAME, $ne.getName(), errors.get( 0 ).getMessage() );
    }
end

rule NAME_NOT_TRIMMED
when
    $ne : NamedElement( name != null, name str[startsWith] " " || name str[endsWith] " " )
then
    reporter.report( DMNMessage.Severity.WARN, $ne , Msg.NAME_NOT_TRIMMED, $ne.getName(), $ne.getClass().getSimpleName(), $ne.getId() );
end

rule NAME_NOT_NORMALIZED
when
    $ne : NamedElement( name != null, name contains "  " )
then
    reporter.report( DMNMessage.Severity.WARN, $ne , Msg.NAME_NOT_NORMALIZED, $ne.getName(), $ne.getClass().getSimpleName(), $ne.getId() );
end

rule VARIABLE_LEADING_TRAILING_SPACES
when
  $ce1 : InformationItem( name != null,
                          name str[startsWith] " " || name str[endsWith] " ",
                          !(parent instanceof Binding || parent instanceof FunctionDefinition || parent instanceof Relation ) )
then
  reporter.report( DMNMessage.Severity.WARN,  $ce1 , Msg.VARIABLE_LEADING_TRAILING_SPACES, $ce1.getName(), $ce1.getParentDRDElement().getIdentifierString() );
end

rule DRGELEM_NOT_UNIQUE
when
  $x : DRGElement( parent instanceof Definitions )
  $y : DRGElement( name == $x.name, parent instanceof Definitions,
                   parent == $x.parent,
                   this != $x )
then
  reporter.report( DMNMessage.Severity.ERROR,  $x , Msg.DUPLICATE_DRG_ELEMENT, $x.getName() );
end

// From DMN Spec: 6.3.3 Import metamodel
rule IMPORT_NAME_NOT_UNIQUE
when
  $x : Import( parent instanceof Definitions )
  $y : Import( name == $x.name, parent instanceof Definitions, parent == $x.parent, this != $x )
then
  reporter.report( DMNMessage.Severity.ERROR,  $x , Msg.IMPORT_NAME_NOT_UNIQUE, $x.getName() );
end

// From DMN Spec: 6.3.3 Import metamodel
rule IMPORT_NAME_NOT_UNIQUE_WITH_DRG
when
  $x : Import( parent instanceof Definitions )
  $y : DRGElement( name == $x.name, parent instanceof Definitions, parent == $x.parent )
then
  reporter.report( DMNMessage.Severity.ERROR,  $x , Msg.IMPORT_NAME_NOT_UNIQUE, $x.getName() );
end

// From DMN Spec: 6.3.3 Import metamodel
rule IMPORT_NAME_NOT_UNIQUE_WITH_ITEMDEF
when
  $x : Import( parent instanceof Definitions )
  $y : ItemDefinition( name == $x.name, parent instanceof Definitions, parent == $x.parent )
then
  reporter.report( DMNMessage.Severity.ERROR,  $x , Msg.IMPORT_NAME_NOT_UNIQUE, $x.getName() );
end

rule FORMAL_PARAM_DUPLICATED
when
    $fp1 : InformationItem( parent instanceof FunctionDefinition )
    $fp2 : InformationItem( name == $fp1.name, parent == $fp1.parent, this != $fp1 )
then
    reporter.report( DMNMessage.Severity.ERROR,  $fp1 , Msg.DUPLICATE_FORMAL_PARAM, $fp1.getName(), $fp1.getParentDRDElement().getIdentifierString() );
end

rule RELATION_DUP_COLUMN
when
  $c1 : InformationItem( parent instanceof Relation )
  $c2 : InformationItem( name == $c1.name, parent == $c1.parent, this != $c1 )
then
  reporter.report( DMNMessage.Severity.ERROR,  $c1 , Msg.DUPLICATED_RELATION_COLUMN, $c1.getName(), $c1.getParentDRDElement().getIdentifierString() );
end

rule INVOCATION_MISSING_EXPRESSION
when
    $inv : Invocation( expression == null || expression#LiteralExpression.text == "" )
then
    reporter.report( DMNMessage.Severity.ERROR,  $inv , Msg.MISSING_EXPRESSION_FOR_INVOCATION, $inv.getParentDRDElement().getIdentifierString() );
end

// The parameter names in the Binding elements SHALL be a subset of the formalParameters of the calledFunction.
rule INVOCATION_INCONSISTENT_PARAM_NAMES
when
    $inv : Invocation( $targetName : expression#LiteralExpression.text )
    $target : BusinessKnowledgeModel( name == $targetName )
    $b : Binding($s : parameter.name) from $inv.binding
    not( InformationItem( name == $s ) from $target.encapsulatedLogic.formalParameter )
then
    reporter.report( DMNMessage.Severity.ERROR,  $b.getParameter() , Msg.UNKNOWN_PARAMETER, $s, $targetName, $inv.getParentDRDElement().getIdentifierString() );
end

// the following rule needs to be improved as an invocation element can be used to invoke
// functions not defined in DRGelements
//rule INVOCATION_MISSING_TARGET
//when
//    $inv : Invocation( $targetName : expression#LiteralExpression.text )
//    not( DRGElement( name == $targetName ) )
//then
//    reporter.report( DMNMessage.Severity.ERROR,  $inv , Msg.INVOCATION_MISSING_TARGET );
//end

rule INVOCATION_WRONG_PARAM_COUNT
when
    $inv : Invocation( $targetName : expression#LiteralExpression.text )
    BusinessKnowledgeModel( name == $targetName, encapsulatedLogic!.formalParameter.size != $inv.binding.size ) 
then
    reporter.report( DMNMessage.Severity.ERROR,  $inv , Msg.PARAMETER_COUNT_MISMATCH, $targetName, $inv.getParentDRDElement().getIdentifierString() );
end

// This is a lower level complement of ITEMDEF_NOT_UNIQUE below, for detecting duplicate attribute names inside the same ItemDefinition
rule ITEMCOMP_DUPLICATED
when
  $ic1 : ItemDefinition( parent instanceof ItemDefinition )
  $ic2 : ItemDefinition( name == $ic1.name, parent == $ic1.parent, this != $ic1 )
then
  reporter.report( DMNMessage.Severity.ERROR,  $ic1 , Msg.DUPLICATED_ITEM_COMPONENT, $ic1.getName(), getRootItemDef( $ic1 ).getName() );
end

rule ITEMDEF_NOT_UNIQUE
when
  $x : ItemDefinition( parent instanceof Definitions )
  $y : ItemDefinition( parent instanceof Definitions, parent == $x.parent, name == $x.name, this != $x )
then
  reporter.report( DMNMessage.Severity.ERROR,  $x , Msg.DUPLICATED_ITEM_DEFINITION, $x.getName() );
end

rule RELATION_ROW_CELL_NOT_LITERAL
when
  $e : Expression( parent instanceof org.kie.dmn.model.api.List, parent.parent instanceof Relation, ! (this instanceof LiteralExpression) )
then
  org.kie.dmn.model.api.List row = (org.kie.dmn.model.api.List) $e.getParent();
  Relation relation = (Relation) row.getParent();
  reporter.report( DMNMessage.Severity.ERROR,  $e , Msg.RELATION_CELL_NOT_LITERAL,
                   relation.getRow().indexOf(row)+1,
                   relation.getParentDRDElement().getIdentifierString() );
end

rule RELATION_ROW_CELLCOUNTMISMATCH
when
  $rel : Relation()
  $row : org.kie.dmn.model.api.List( expression.size != $rel.column.size ) from $rel.row
then
  reporter.report( DMNMessage.Severity.ERROR,  $row , Msg.RELATION_CELL_COUNT_MISMATCH,
                   $rel.getRow().indexOf($row)+1,
                   $rel.getParentDRDElement().getIdentifierString() );
end




© 2015 - 2025 Weber Informatics LLC | Privacy Policy