/* * Copyright 2013 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.drools.workbench.models.commons.backend.rule.context; import java.util.Set; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.rule.ActionFieldValue; import org.drools.workbench.models.datamodel.rule.ActionInsertFact; import org.drools.workbench.models.datamodel.rule.ActionSetField; import org.drools.workbench.models.datamodel.rule.ActionUpdateField; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.CompositeFactPattern; import org.drools.workbench.models.datamodel.rule.CompositeFieldConstraint; import org.drools.workbench.models.datamodel.rule.ConnectiveConstraint; import org.drools.workbench.models.datamodel.rule.DSLSentence; import org.drools.workbench.models.datamodel.rule.FactPattern; import org.drools.workbench.models.datamodel.rule.FieldConstraint; import org.drools.workbench.models.datamodel.rule.FieldNatureType; import org.drools.workbench.models.datamodel.rule.FreeFormLine; import org.drools.workbench.models.datamodel.rule.FromAccumulateCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.FromCollectCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.FromCompositeFactPattern; import org.drools.workbench.models.datamodel.rule.IAction; import org.drools.workbench.models.datamodel.rule.IFactPattern; import org.drools.workbench.models.datamodel.rule.IPattern; import org.drools.workbench.models.datamodel.rule.InterpolationVariable; import org.drools.workbench.models.datamodel.rule.RuleModel; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraint; import org.drools.workbench.models.datamodel.rule.SingleFieldConstraintEBLeftSide; import org.drools.workbench.models.datamodel.rule.visitors.ToStringExpressionVisitor; /** * A Rule Model Visitor to extract Interpolation Variables (Template Keys). This version * also identifies whether components of a RuleModel use non-template constraints. */ public class GeneratorContextRuleModelVisitor { private IFactPattern factPattern; private RuleModel model = new RuleModel(); private Set<InterpolationVariable> vars; private boolean hasNonTemplateOutput; public GeneratorContextRuleModelVisitor( final Set<InterpolationVariable> vars ) { this.vars = vars; } public GeneratorContextRuleModelVisitor( final IPattern pattern, final Set<InterpolationVariable> vars ) { this.vars = vars; this.model.addLhsItem( pattern ); } public GeneratorContextRuleModelVisitor( final IAction action, final Set<InterpolationVariable> vars ) { this.vars = vars; this.model.addRhsItem( action ); } private void parseStringPattern( final String text ) { if ( text == null || text.length() == 0 ) { return; } int pos = 0; while ( ( pos = text.indexOf( "@{", pos ) ) != -1 ) { int end = text.indexOf( '}', pos + 2 ); if ( end != -1 ) { final String varName = text.substring( pos + 2, end ); pos = end + 1; InterpolationVariable var = new InterpolationVariable( varName, DataType.TYPE_OBJECT ); if ( !vars.contains( var ) ) { vars.add( var ); } } } } public void visit( final Object o ) { if ( o == null ) { return; } if ( o instanceof RuleModel ) { visitRuleModel( (RuleModel) o ); } else if ( o instanceof FactPattern ) { visitFactPattern( (FactPattern) o ); } else if ( o instanceof CompositeFieldConstraint ) { visitCompositeFieldConstraint( (CompositeFieldConstraint) o ); } else if ( o instanceof SingleFieldConstraintEBLeftSide ) { visitSingleFieldConstraint( (SingleFieldConstraintEBLeftSide) o ); } else if ( o instanceof SingleFieldConstraint ) { visitSingleFieldConstraint( (SingleFieldConstraint) o ); } else if ( o instanceof CompositeFactPattern ) { visitCompositeFactPattern( (CompositeFactPattern) o ); } else if ( o instanceof FreeFormLine ) { visitFreeFormLine( (FreeFormLine) o ); } else if ( o instanceof FromAccumulateCompositeFactPattern ) { visitFromAccumulateCompositeFactPattern( (FromAccumulateCompositeFactPattern) o ); } else if ( o instanceof FromCollectCompositeFactPattern ) { visitFromCollectCompositeFactPattern( (FromCollectCompositeFactPattern) o ); } else if ( o instanceof FromCompositeFactPattern ) { visitFromCompositeFactPattern( (FromCompositeFactPattern) o ); } else if ( o instanceof DSLSentence ) { visitDSLSentence( (DSLSentence) o ); } else if ( o instanceof ActionInsertFact ) { visitActionFieldList( (ActionInsertFact) o ); } else if ( o instanceof ActionUpdateField ) { visitActionFieldList( (ActionUpdateField) o ); } else if ( o instanceof ActionSetField ) { visitActionFieldList( (ActionSetField) o ); } else if ( o instanceof ActionFieldValue ) { visitActionFieldValue( (ActionFieldValue) o ); } } //ActionInsertFact, ActionSetField, ActionpdateField private void visitActionFieldList( final ActionInsertFact afl ) { String factType = afl.getFactType(); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), afv.getType(), factType, afv.getField() ); if ( afv.getNature() == FieldNatureType.TYPE_TEMPLATE && !vars.contains( var ) ) { vars.add( var ); } else { hasNonTemplateOutput = true; } } } private void visitActionFieldList( final ActionSetField afl ) { String factType = model.getLHSBindingType( afl.getVariable() ); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), afv.getType(), factType, afv.getField() ); if ( afv.getNature() == FieldNatureType.TYPE_TEMPLATE && !vars.contains( var ) ) { vars.add( var ); } else { hasNonTemplateOutput = true; } } } private void visitActionFieldList( final ActionUpdateField afl ) { String factType = model.getLHSBindingType( afl.getVariable() ); for ( ActionFieldValue afv : afl.getFieldValues() ) { InterpolationVariable var = new InterpolationVariable( afv.getValue(), afv.getType(), factType, afv.getField() ); if ( afv.getNature() == FieldNatureType.TYPE_TEMPLATE && !vars.contains( var ) ) { vars.add( var ); } else { hasNonTemplateOutput = true; } } } private void visitActionFieldValue( final ActionFieldValue afv ) { if ( afv.getNature() != FieldNatureType.TYPE_TEMPLATE ) { hasNonTemplateOutput = true; } } private void visitCompositeFactPattern( final CompositeFactPattern pattern ) { if ( pattern.getPatterns() != null ) { for ( IFactPattern fp : pattern.getPatterns() ) { visit( fp ); } } } private void visitCompositeFieldConstraint( final CompositeFieldConstraint cfc ) { if ( cfc.getConstraints() != null ) { for ( FieldConstraint fc : cfc.getConstraints() ) { visit( fc ); } } } //TODO Handle definition and value private void visitDSLSentence( final DSLSentence sentence ) { String text = sentence.getDefinition(); parseStringPattern( text ); } private void visitFactPattern( final FactPattern pattern ) { this.factPattern = pattern; for ( FieldConstraint fc : pattern.getFieldConstraints() ) { visit( fc ); } } private void visitFreeFormLine( final FreeFormLine ffl ) { parseStringPattern( ffl.getText() ); } private void visitFromAccumulateCompositeFactPattern( final FromAccumulateCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); visit( pattern.getSourcePattern() ); parseStringPattern( pattern.getActionCode() ); parseStringPattern( pattern.getInitCode() ); parseStringPattern( pattern.getReverseCode() ); } private void visitFromCollectCompositeFactPattern( final FromCollectCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); visit( pattern.getRightPattern() ); } private void visitFromCompositeFactPattern( final FromCompositeFactPattern pattern ) { visit( pattern.getFactPattern() ); ToStringExpressionVisitor visitor = new ToStringExpressionVisitor(); parseStringPattern( pattern.getExpression().getText( visitor ) ); } private void visitRuleModel( final RuleModel model ) { this.model = model; if ( model.lhs != null ) { for ( IPattern pat : model.lhs ) { visit( pat ); } } if ( model.rhs != null ) { for ( IAction action : model.rhs ) { visit( action ); } } } private void visitSingleFieldConstraint( final SingleFieldConstraint sfc ) { final InterpolationVariable var = new InterpolationVariable( sfc.getValue(), sfc.getFieldType(), ( factPattern == null ? "" : factPattern.getFactType() ), sfc.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == sfc.getConstraintValueType() && !vars.contains( var ) ) { vars.add( var ); } else { hasNonTemplateOutput = true; } //Visit Connection constraints if ( sfc.getConnectives() != null ) { for ( int i = 0; i < sfc.getConnectives().length; i++ ) { final ConnectiveConstraint cc = sfc.getConnectives()[ i ]; InterpolationVariable ccVar = new InterpolationVariable( cc.getValue(), cc.getFieldType(), ( factPattern == null ? "" : factPattern.getFactType() ), cc.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == cc.getConstraintValueType() && !vars.contains( ccVar ) ) { vars.add( ccVar ); } else { hasNonTemplateOutput = true; } } } } private void visitSingleFieldConstraint( final SingleFieldConstraintEBLeftSide sfexp ) { final String genericType = sfexp.getExpressionLeftSide().getGenericType(); String factType = sfexp.getExpressionLeftSide().getPreviousClassType(); if ( factType == null ) { factType = sfexp.getExpressionLeftSide().getClassType(); } final InterpolationVariable var = new InterpolationVariable( sfexp.getValue(), genericType, factType, sfexp.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == sfexp.getConstraintValueType() && !vars.contains( var ) ) { vars.add( var ); } else { hasNonTemplateOutput = true; } //Visit Connection constraints if ( sfexp.getConnectives() != null ) { for ( int i = 0; i < sfexp.getConnectives().length; i++ ) { final ConnectiveConstraint cc = sfexp.getConnectives()[ i ]; InterpolationVariable ccVar = new InterpolationVariable( cc.getValue(), genericType, factType, cc.getFieldName() ); if ( BaseSingleFieldConstraint.TYPE_TEMPLATE == cc.getConstraintValueType() && !vars.contains( ccVar ) ) { vars.add( ccVar ); } else { hasNonTemplateOutput = true; } } } } public boolean hasNonTemplateOutput() { return hasNonTemplateOutput; } }