/**
* 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.client.modeldriven.dt;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.drools.ide.common.client.modeldriven.FieldNature;
import org.drools.ide.common.client.modeldriven.brl.ActionFieldList;
import org.drools.ide.common.client.modeldriven.brl.ActionFieldValue;
import org.drools.ide.common.client.modeldriven.brl.CompositeFactPattern;
import org.drools.ide.common.client.modeldriven.brl.CompositeFieldConstraint;
import org.drools.ide.common.client.modeldriven.brl.DSLSentence;
import org.drools.ide.common.client.modeldriven.brl.FactPattern;
import org.drools.ide.common.client.modeldriven.brl.FieldConstraint;
import org.drools.ide.common.client.modeldriven.brl.FreeFormLine;
import org.drools.ide.common.client.modeldriven.brl.FromAccumulateCompositeFactPattern;
import org.drools.ide.common.client.modeldriven.brl.FromCollectCompositeFactPattern;
import org.drools.ide.common.client.modeldriven.brl.FromCompositeFactPattern;
import org.drools.ide.common.client.modeldriven.brl.IAction;
import org.drools.ide.common.client.modeldriven.brl.IPattern;
import org.drools.ide.common.client.modeldriven.brl.BaseSingleFieldConstraint;
import org.drools.ide.common.client.modeldriven.brl.PortableObject;
import org.drools.ide.common.client.modeldriven.brl.RuleModel;
import org.drools.ide.common.client.modeldriven.brl.SingleFieldConstraint;
public class TemplateModel extends RuleModel implements PortableObject {
public static final String ID_COLUMN_NAME = "__ID_KOL_NAME__";
private long idCol = 0;
private Map<String, List<String>> table = new HashMap<String, List<String>>();
private int rowsCount = 0;
public int getColsCount() {
return getInterpolationVariables().size() - 1;
}
public int getRowsCount() {
return rowsCount;
}
private String getNewIdColValue() {
idCol++;
return String.valueOf(idCol);
}
public String addRow(String[] row) {
return addRow(null, row);
}
public String addRow(String rowId, String[] row) {
Map<String, Integer> vars = getInterpolationVariables();
if (row.length != vars.size() - 1) {
throw new IllegalArgumentException("Invalid numbers of columns: " + row.length + " expected: "
+ vars.size());
}
if (rowId == null || rowId.length() == 0) {
rowId = getNewIdColValue();
}
for (Map.Entry<String, Integer> entry : vars.entrySet()) {
List<String> list = table.get(entry.getKey());
if (list == null) {
list = new ArrayList<String>();
table.put(entry.getKey(), list);
}
if (rowsCount != list.size()) {
throw new IllegalArgumentException("invalid list size for " + entry.getKey() + ", expected: "
+ rowsCount + " was: " + list.size());
}
if (ID_COLUMN_NAME.equals(entry.getKey())) {
list.add(rowId);
} else {
list.add(row[entry.getValue()]);
}
}
rowsCount++;
return rowId;
}
public boolean removeRowById(String rowId) {
int idx = table.get(ID_COLUMN_NAME).indexOf(rowId);
if (idx != -1) {
for (List<String> col : table.values()) {
col.remove(idx);
}
rowsCount--;
}
return idx != -1;
}
public void removeRow(int row) {
if (row >= 0 && row < rowsCount) {
for (List<String> col : table.values()) {
col.remove(row);
}
rowsCount--;
} else {
throw new ArrayIndexOutOfBoundsException(row);
}
}
public void clearRows() {
if (rowsCount > 0) {
for (List<String> col : table.values()) {
col.clear();
}
rowsCount = 0;
}
}
public void putInSync() {
Map<String, Integer> vars = getInterpolationVariables();
table.keySet().retainAll(vars.keySet());
vars.keySet().removeAll(table.keySet());
List<String> aux = new ArrayList<String>(rowsCount);
for (int i = 0; i < rowsCount; i++) {
aux.add("");
}
for (String varName : vars.keySet()) {
table.put(varName, new ArrayList<String>(aux));
}
}
public String[] getInterpolationVariablesList() {
Map<String, Integer> vars = getInterpolationVariables();
String[] ret = new String[vars.size() - 1];
for (Map.Entry<String, Integer> entry: vars.entrySet()) {
if (!ID_COLUMN_NAME.equals(entry.getKey())) {
ret[entry.getValue()] = entry.getKey();
}
}
return ret;
}
private Map<String, Integer> getInterpolationVariables() {
Map<String, Integer> result = new HashMap<String, Integer>();
new RuleModelVisitor(result).visit(this);
result.put(ID_COLUMN_NAME, result.size());
return result;
}
public Map<String, List<String>> getTable() {
return table;
}
public String[][] getTableAsArray() {
if (rowsCount <= 0) {
return new String[0][0];
}
String[][] ret = new String[rowsCount][table.size() - 1];
Map<String, Integer> vars = getInterpolationVariables();
for (Map.Entry<String, Integer> entry : vars.entrySet()) {
String varName = entry.getKey();
if (ID_COLUMN_NAME.equals(entry.getKey())) {
continue;
}
int idx = entry.getValue();
for (int row = 0; row < rowsCount; row++) {
ret[row][idx] = table.get(varName).get(row);
}
}
return ret;
}
public void setValue(String varName, int rowIndex, String newValue) {
getTable().get(varName).set(rowIndex, newValue);
}
public static class RuleModelVisitor {
private Map<String, Integer> vars;
public RuleModelVisitor(Map<String, Integer> vars) {
this.vars = vars;
}
public void visit(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 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 ActionFieldList) {
visitActionFieldList((ActionFieldList) o);
}
}
private void visitActionFieldList(ActionFieldList afl) {
for (ActionFieldValue afv : afl.fieldValues) {
if (afv.nature == FieldNature.TYPE_TEMPLATE && !vars.containsKey(afv.value)) {
vars.put(afv.value, vars.size());
}
}
}
public void visitRuleModel(RuleModel 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 visitFactPattern(FactPattern pattern) {
for (FieldConstraint fc : pattern.getFieldConstraints()) {
visit(fc);
}
}
private void visitCompositeFieldConstraint(CompositeFieldConstraint cfc) {
if (cfc.constraints != null) {
for (FieldConstraint fc : cfc.constraints) {
visit(fc);
}
}
}
private void visitSingleFieldConstraint(SingleFieldConstraint sfc) {
if (BaseSingleFieldConstraint.TYPE_TEMPLATE == sfc.getConstraintValueType() && !vars.containsKey(sfc.getValue())) {
vars.put(sfc.getValue(), vars.size());
}
}
private void visitFreeFormLine(FreeFormLine ffl) {
parseStringPattern(ffl.text);
}
private void visitCompositeFactPattern(CompositeFactPattern pattern) {
if (pattern.patterns != null) {
for (FactPattern fp : pattern.patterns) {
visit(fp);
}
}
}
private void visitFromCompositeFactPattern(FromCompositeFactPattern pattern) {
visit(pattern.getFactPattern());
parseStringPattern(pattern.getExpression().getText());
}
private void visitFromCollectCompositeFactPattern(FromCollectCompositeFactPattern pattern) {
visit(pattern.getFactPattern());
visit(pattern.getRightPattern());
}
private void visitFromAccumulateCompositeFactPattern(FromAccumulateCompositeFactPattern pattern) {
visit(pattern.getFactPattern());
visit(pattern.getSourcePattern());
parseStringPattern(pattern.getActionCode());
parseStringPattern(pattern.getInitCode());
parseStringPattern(pattern.getReverseCode());
}
private void visitDSLSentence(final DSLSentence sentence) {
parseStringPattern(sentence.sentence);
}
private void parseStringPattern(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) {
String var = text.substring(pos + 2, end);
pos = end + 1;
if (!vars.containsKey(var)) {
vars.put(var, vars.size());
}
}
}
}
}
}