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

org.drools.ide.common.server.util.BRDRLPersistence Maven / Gradle / Ivy

There is a newer version: 5.1.1
Show newest version
/**
 * Copyright 2010 JBoss Inc
 *
 * 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.ide.common.server.util;

import org.drools.core.util.ReflectiveVisitor;
import org.drools.ide.common.client.modeldriven.SuggestionCompletionEngine;
import org.drools.ide.common.client.modeldriven.brl.*;

/**
 * This class persists the rule model to DRL and back
 * 
 * @author etirelli
 */
public class BRDRLPersistence implements BRLPersistence {

    private static final BRLPersistence INSTANCE = new BRDRLPersistence();

    protected BRDRLPersistence() {
    }

    public static BRLPersistence getInstance() {
        return INSTANCE;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * org.drools.ide.common.server.util.BRLPersistence#marshal(org.drools.guvnor
     * .client.modeldriven.brl.RuleModel)
     */
    public String marshal(RuleModel model) {
        return marshalRule(model);
    }
    
    protected String marshalRule(RuleModel model) {
    	boolean isDSLEnhanced = model.hasDSLSentences();

        StringBuilder buf = new StringBuilder();
        this.marshalHeader(model, buf);
        this.marshalMetadata(buf, model);
        this.marshalAttributes(buf, model);

        buf.append("\twhen\n");
        this.marshalLHS(buf, model, isDSLEnhanced);
        buf.append("\tthen\n");
        this.marshalRHS(buf, model, isDSLEnhanced);
        this.marshalFooter(buf);
        return buf.toString();
	}

	protected void marshalFooter(StringBuilder buf) {
		buf.append("end\n");
	}

	protected void marshalHeader(RuleModel model, StringBuilder buf) {
		buf.append("rule \"" + marshalRuleName(model) + "\"");
        if (null != model.parentName && model.parentName.length() > 0) {
            buf.append(" extends \"" + model.parentName + "\"\n");
        } else {
            buf.append('\n');
        }
	}

	protected String marshalRuleName(RuleModel model) {
		return model.name;
	}

    /**
     * @see
     * org.drools.ide.common.server.util.BRLPersistence#unmarshal(java.lang.String)
     */
    public RuleModel unmarshal(String str) {
        throw new UnsupportedOperationException(
                "Still not possible to convert pure DRL to RuleModel");
    }

    /**
     * Marshal model attributes
     *
     * @param buf
     * @param model
     */
    private void marshalAttributes(StringBuilder buf, RuleModel model) {
        boolean hasDialect = false;
        for (int i = 0; i < model.attributes.length; i++) {
            RuleAttribute attr = model.attributes[i];

            buf.append("\t");
            buf.append(attr);

            buf.append("\n");
            if (attr.attributeName.equals("dialect")) {
                hasDialect = true;
            }
        }
        // Un comment below for mvel
        if (!hasDialect) {
            RuleAttribute attr = new RuleAttribute("dialect", "mvel");
            buf.append("\t");
            buf.append(attr);
            buf.append("\n");
        }
    }

    /**
     * Marshal model metadata
     *
     * @param buf
     * @param model
     */
    private void marshalMetadata(StringBuilder buf, RuleModel model) {
        if (model.metadataList != null) {
            for (int i = 0; i < model.metadataList.length; i++) {
                buf.append("\t").append(model.metadataList[i]).append("\n");
            }
        }
    }

    /**
     * Marshal LHS patterns
     *
     * @param buf
     * @param model
     */
    private void marshalLHS(StringBuilder buf, RuleModel model,
            boolean isDSLEnhanced) {
		if (model.lhs != null) {
			LHSPatternVisitor visitor = new LHSPatternVisitor(isDSLEnhanced, buf);
			for (IPattern cond : model.lhs) {
				visitor.visit(cond);
			}
		}
    }

    private void marshalRHS(StringBuilder buf, RuleModel model,
            boolean isDSLEnhanced) {
		if (model.rhs != null) {
			RHSActionVisitor visitor = new RHSActionVisitor(isDSLEnhanced, buf);
			for (IAction action : model.rhs) {
				visitor.visit(action);
			}
		}
    }

    public static class LHSPatternVisitor extends ReflectiveVisitor {

        private StringBuilder buf;
        private boolean isDSLEnhanced;

        public LHSPatternVisitor(boolean isDSLEnhanced, StringBuilder b) {
            this.isDSLEnhanced = isDSLEnhanced;
            buf = b;
        }

        public void visitFactPattern(FactPattern pattern) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                // adding passthrough markup
                buf.append(">");
            }
            generateFactPattern(pattern);
            buf.append("\n");
        }

        public void visitFreeFormLine(FreeFormLine ffl) {

            this.buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            this.buf.append(ffl.text);
            this.buf.append("\n");
        }

        public void visitCompositeFactPattern(CompositeFactPattern pattern) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                // adding passthrough markup
                buf.append(">");
            }
            if (CompositeFactPattern.COMPOSITE_TYPE_EXISTS.equals(pattern.type)) {
                renderCompositeFOL(pattern);
            } else if (CompositeFactPattern.COMPOSITE_TYPE_NOT.equals(pattern.type)) {
                renderCompositeFOL(pattern);
            } else if (CompositeFactPattern.COMPOSITE_TYPE_OR.equals(pattern.type)) {
                buf.append("( ");
                if (pattern.patterns != null) {
                    for (int i = 0; i < pattern.patterns.length; i++) {
                        if (i > 0) {
                            buf.append(" ");
                            buf.append(pattern.type);
                            buf.append(" ");
                        }
                        renderSubPattern(pattern, i);
                    }
                }
                buf.append(" )\n");
            }
        }

        public void visitFromCompositeFactPattern(FromCompositeFactPattern pattern) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                // adding passthrough markup
                buf.append(">");
            }
            if (pattern.getFactPattern() != null) {
                generateFactPattern(pattern.getFactPattern());
            }
            buf.append(" from\n\t\t  ");
            renderExpression(pattern.getExpression());
            buf.append("\n");
        }

        public void visitFromCollectCompositeFactPattern(FromCollectCompositeFactPattern pattern) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                // adding passthrough markup
                buf.append(">");
            }
            if (pattern.getFactPattern() != null) {
                generateFactPattern(pattern.getFactPattern());
            }
            buf.append(" from collect ( ");
            if (pattern.getRightPattern() != null) {
                if (pattern.getRightPattern() instanceof FactPattern) {
                    generateFactPattern((FactPattern) pattern.getRightPattern());
                } else if (pattern.getRightPattern() instanceof FromAccumulateCompositeFactPattern) {
                    visitFromAccumulateCompositeFactPattern((FromAccumulateCompositeFactPattern) pattern.getRightPattern());
                } else if (pattern.getRightPattern() instanceof FromCollectCompositeFactPattern) {
                    visitFromCollectCompositeFactPattern((FromCollectCompositeFactPattern) pattern.getRightPattern());
                } else if (pattern.getRightPattern() instanceof FromCompositeFactPattern) {
                    visitFromCompositeFactPattern((FromCompositeFactPattern) pattern.getRightPattern());
                } else if (pattern.getRightPattern() instanceof FreeFormLine) {
                    visitFreeFormLine((FreeFormLine) pattern.getRightPattern());
                } else {
                    throw new IllegalArgumentException("Unuported pattern " + pattern.getRightPattern() + " for FROM COLLECT");
                }
            }
            buf.append(") \n");
        }

        public void visitFromAccumulateCompositeFactPattern(FromAccumulateCompositeFactPattern pattern) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                // adding passthrough markup
                buf.append(">");
            }
            if (pattern.getFactPattern() != null) {
                generateFactPattern(pattern.getFactPattern());
            }
            buf.append(" from accumulate ( ");
            if (pattern.getSourcePattern() != null) {
                if (pattern.getSourcePattern() instanceof FactPattern) {
                    generateFactPattern((FactPattern) pattern.getSourcePattern());
                } else if (pattern.getSourcePattern() instanceof FromAccumulateCompositeFactPattern) {
                    visitFromAccumulateCompositeFactPattern((FromAccumulateCompositeFactPattern) pattern.getSourcePattern());
                } else if (pattern.getSourcePattern() instanceof FromCollectCompositeFactPattern) {
                    visitFromCollectCompositeFactPattern((FromCollectCompositeFactPattern) pattern.getSourcePattern());
                } else if (pattern.getSourcePattern() instanceof FromCompositeFactPattern) {
                    visitFromCompositeFactPattern((FromCompositeFactPattern) pattern.getSourcePattern());
                } else {
                    throw new IllegalArgumentException("Unuported pattern " + pattern.getSourcePattern() + " for FROM ACCUMULATE");
                }
            }
            buf.append(",\n");

            if (pattern.useFunctionOrCode().equals(FromAccumulateCompositeFactPattern.USE_FUNCTION)){
                buf.append("\t\t\t");
                buf.append(pattern.getFunction());
            }else{
                buf.append("\t\t\tinit( ");
                buf.append(pattern.getInitCode());
                buf.append(" ),\n");
                buf.append("\t\t\taction( ");
                buf.append(pattern.getActionCode());
                buf.append(" ),\n");
                if (pattern.getReverseCode() != null && !pattern.getReverseCode().trim().equals("")) {
                    buf.append("\t\t\treverse( ");
                    buf.append(pattern.getReverseCode());
                    buf.append(" ),\n");
                }
                buf.append("\t\t\tresult( ");
                buf.append(pattern.getResultCode());
                buf.append(" )\n");
            }
            buf.append(") \n");


        }

        private void renderCompositeFOL(CompositeFactPattern pattern) {
            buf.append(pattern.type);
            if (pattern.patterns != null && pattern.patterns.length > 1) {
                buf.append(" (");
                for (int i = 0; i < pattern.patterns.length; i++) {
                    renderSubPattern(pattern, i);
                    if (i != pattern.patterns.length - 1) {
                        buf.append(" and ");
                    }
                }
                buf.append(") \n");
            } else {
                buf.append(" ");
                renderSubPattern(pattern, 0);
                buf.append("\n");
            }
        }

        private void renderSubPattern(CompositeFactPattern pattern, int subIndex) {
            if (pattern.patterns == null || pattern.patterns.length == 0) {
                return;
            }
            this.generateFactPattern(pattern.patterns[subIndex]);
        }

        private void renderExpression(ExpressionFormLine expression) {
            buf.append(expression.getText());
        }

        public void visitDSLSentence(final DSLSentence sentence) {
            buf.append("\t\t");
            buf.append(sentence);
            buf.append("\n");
        }

        private void generateFactPattern(FactPattern pattern) {
            if (pattern.boundName != null) {
                buf.append(pattern.boundName);
                buf.append(" : ");
            }
            if (pattern.factType != null) {
                buf.append(pattern.factType);
            }
            buf.append("( ");

            // top level constraints
            if (pattern.constraintList != null) {
                generateConstraints(pattern);
            }
            buf.append(")");
        }

        private void generateConstraints(FactPattern pattern) {
            int printedCount = 0;
            for (int i = 0; i < pattern.getFieldConstraints().length; i++) {
                StringBuilder buffer = new StringBuilder();
                generateConstraint(pattern.constraintList.constraints[i],
                        false, buffer);
                if (buffer.length() > 0) {
                    if (printedCount > 0) {
                        buf.append(", ");
                    }
                    buf.append(buffer);
                    printedCount++;
                }
            }
        }

        /**
         * Recursively process the nested constraints. It will only put brackets
         * in for the ones that aren't at top level. This makes for more
         * readable DRL in the most common cases.
         */
        private void generateConstraint(FieldConstraint con, boolean nested,
                StringBuilder buf) {
            if (con instanceof CompositeFieldConstraint) {
                CompositeFieldConstraint cfc = (CompositeFieldConstraint) con;
                if (nested) {
                    buf.append("( ");
                }
                FieldConstraint[] nestedConstraints = cfc.constraints;
                if (nestedConstraints != null) {
                    for (int i = 0; i < nestedConstraints.length; i++) {
                        generateConstraint(nestedConstraints[i], true, buf);
                        if (i < (nestedConstraints.length - 1)) {
                            // buf.append(" ) ");
                            buf.append(cfc.compositeJunctionType + " ");
                            // buf.append(" ( ");
                        }
                    }
                }
                if (nested) {
                    buf.append(")");
                }
            } else {
                generateSingleFieldConstraint((SingleFieldConstraint) con, buf);
            }
        }

        private void generateSingleFieldConstraint(
                final SingleFieldConstraint constr, StringBuilder buf) {
            if (constr.getConstraintValueType() == BaseSingleFieldConstraint.TYPE_PREDICATE) {
                buf.append("eval( ");
                buf.append(constr.getValue());
                buf.append(" )");
            } else {
                if (constr.getFieldBinding() != null) {
                    buf.append(constr.getFieldBinding());
                    buf.append(" : ");
                }
                if ((constr.getOperator() != null && constr.getValue() != null)
                        || constr.getFieldBinding() != null 
                        || constr.getConstraintValueType() == BaseSingleFieldConstraint.TYPE_EXPR_BUILDER_VALUE
                        || constr instanceof SingleFieldConstraintEBLeftSide) {
                    SingleFieldConstraint parent = (SingleFieldConstraint) constr.getParent();
                    StringBuilder parentBuf = new StringBuilder();
                    while (parent != null) {
                        parentBuf.insert(0, parent.getFieldName() + ".");
                        parent = (SingleFieldConstraint) parent.getParent();
                    }
                    buf.append(parentBuf);
                    if (constr instanceof SingleFieldConstraintEBLeftSide) {
                    	buf.append(((SingleFieldConstraintEBLeftSide) constr).getExpressionLeftSide().getText());
                    } else {
                    	buf.append(constr.getFieldName());
                    }
                }
                
                addFieldRestriction(buf, constr.getConstraintValueType(), constr.getOperator(), constr.getValue(), constr
                		.getExpressionValue());
                
				// and now do the connectives.
                if (constr.connectives != null) {
                    for (int j = 0; j < constr.connectives.length; j++) {
                        final ConnectiveConstraint conn = constr.connectives[j];
                        addFieldRestriction(buf, conn.getConstraintValueType(),
                                conn.operator, conn.getValue(),null);
                    }
                }
            }
        }

        private void addFieldRestriction(final StringBuilder buf,
                final int type, final String operator, final String value,
                final ExpressionFormLine expression) {
            if (operator == null) {
                return;
            }

            buf.append(" ");
            buf.append(operator);
            buf.append(" ");
            switch (type) {
                case BaseSingleFieldConstraint.TYPE_RET_VALUE:
                    buf.append("( ");
                    buf.append(value);
                    buf.append(" )");
                    break;
                case BaseSingleFieldConstraint.TYPE_LITERAL:
                    if (operator.equals("in")) {
                        buf.append(value);
                    } else {
                        buf.append('"');
                        buf.append(value);
                        buf.append('"');
                    }
                    break;
                case BaseSingleFieldConstraint.TYPE_EXPR_BUILDER_VALUE:
                    if (expression!=null){
                        buf.append(expression.getText());
                    }
                    break;
                case BaseSingleFieldConstraint.TYPE_TEMPLATE:
                	buf.append("@{").append(value).append("}");
                	break;
                default:
                    buf.append(value);
            }
            buf.append(" ");
        }
    }

    public static class RHSActionVisitor extends ReflectiveVisitor {

        private StringBuilder buf;
        private boolean isDSLEnhanced;
        private int idx = 0;

        public RHSActionVisitor(boolean isDSLEnhanced, StringBuilder b) {
            this.isDSLEnhanced = isDSLEnhanced;
            buf = b;
        }

        public void visitActionInsertFact(final ActionInsertFact action) {
            this.generateInsertCall(action, false);
        }

        public void visitActionInsertLogicalFact(
                final ActionInsertLogicalFact action) {
            this.generateInsertCall(action, true);
        }

        public void visitFreeFormLine(FreeFormLine ffl) {

            this.buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            this.buf.append(ffl.text);
            this.buf.append("\n");
        }

        private void generateInsertCall(final ActionInsertFact action,
                final boolean isLogic) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            if (action.fieldValues.length == 0 && action.getBoundName() == null) {
                buf.append((isLogic) ? "insertLogical( new " : "insert( new ");

                buf.append(action.factType);
                buf.append("() );\n");
            } else {
                buf.append(action.factType);
                if (action.getBoundName() == null) {
                    buf.append(" fact");
                    buf.append(idx);
                } else {
                    buf.append(" " + action.getBoundName());
                }
                buf.append(" = new ");
                buf.append(action.factType);
                buf.append("();\n");
                if (action.getBoundName() == null) {
                    generateSetMethodCalls("fact" + idx, action.fieldValues);
                } else {
                    generateSetMethodCalls(action.getBoundName(), action.fieldValues);
                }

                buf.append("\t\t");
                if (isDSLEnhanced) {
                    buf.append(">");
                }
                if (isLogic) {
                    buf.append("insertLogical(");
                    if (action.getBoundName() == null) {
                        buf.append("fact");
                        buf.append(idx++);
                    } else {
                        buf.append(action.getBoundName());
                    }
                    buf.append(" );\n");
                } else {
                    buf.append("insert(");
                    if (action.getBoundName() == null) {
                        buf.append("fact");
                        buf.append(idx++);
                    } else {
                        buf.append(action.getBoundName());
                    }

                    buf.append(" );\n");
                }
//				buf.append(idx++);
//				buf.append(" );\n");
            }
        }

        public void visitActionUpdateField(final ActionUpdateField action) {
            this.visitActionSetField(action);
            buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            buf.append("update( ");
            buf.append(action.variable);
            buf.append(" );\n");
        }

        public void visitActionGlobalCollectionAdd(
                final ActionGlobalCollectionAdd add) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            buf.append(add.globalName + ".add(" + add.factName + ");\n");
        }

        public void visitActionRetractFact(final ActionRetractFact action) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            buf.append("retract( ");
            buf.append(action.variableName);
            buf.append(" );\n");
        }

        public void visitDSLSentence(final DSLSentence sentence) {
            buf.append("\t\t");
            buf.append(sentence.toString());
            buf.append("\n");
        }

        public void visitActionSetField(final ActionSetField action) {
            if (action instanceof ActionCallMethod) {
                this.generateSetMethodCallsMethod((ActionCallMethod) action,
                        action.fieldValues);
            } else {
                this.generateSetMethodCalls(action.variable,
                        action.fieldValues);
            }
        }

        private void generateSetMethodCalls(final String variableName,
                final ActionFieldValue[] fieldValues) {
            for (int i = 0; i < fieldValues.length; i++) {
                buf.append("\t\t");
                if (isDSLEnhanced) {
                    buf.append(">");
                }
                buf.append(variableName);

                ActionFieldValue value = fieldValues[i];
                if (value instanceof ActionFieldFunction) {
                    buf.append(".");
                    buf.append(value.field);
                } else {
                    buf.append(".set");
                    buf.append(Character.toUpperCase(fieldValues[i].field.charAt(0)));
                    buf.append(fieldValues[i].field.substring(1));
                }
                buf.append("( ");
                if (fieldValues[i].isFormula()) {
                    buf.append(fieldValues[i].value.substring(1));
                } else if (fieldValues[i].nature == ActionFieldValue.TYPE_TEMPLATE) {
                	buf.append("@{").append(fieldValues[i].value).append("}");
                } else if (SuggestionCompletionEngine.TYPE_STRING.equals(fieldValues[i].type)) {
                    buf.append("\"");
                    buf.append(generateFieldValue(fieldValues[i]));
                    buf.append("\"");
                } else {
                    buf.append(generateFieldValue(fieldValues[i]));
                }
                buf.append(" );\n");
            }
        }

		private String generateFieldValue(final ActionFieldValue fieldValue) {
			return fieldValue.value;
		}

        private void generateSetMethodCallsMethod(final ActionCallMethod action,
                final ActionFieldValue[] fieldValues) {
            buf.append("\t\t");
            if (isDSLEnhanced) {
                buf.append(">");
            }
            buf.append(action.variable);
            buf.append(".");

            buf.append(action.methodName);

            buf.append("(");
            boolean isFirst = true;
            for (int i = 0; i < fieldValues.length; i++) {
                ActionFieldFunction valueFunction = (ActionFieldFunction) fieldValues[i];
                if (isFirst == true) {
                    isFirst = false;
                } else {
                    buf.append(",");
                }

                buf.append(valueFunction.value);
            }
            buf.append(" );\n");

        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy