@Test
//https://issues.jboss.org/browse/GUVNOR-2888
public void conversionWithRetract() {

    final ConversionResult result = new ConversionResult();
    final List<DataListener> listeners = new ArrayList<>();
    addModelField("org.test.Employee",
                  "this",
                  "org.test.Employee",
                  DataType.TYPE_THIS);
    addModelField("org.test.Employee",
                  "yearsOfService",
                  Integer.class.getName(),
                  DataType.TYPE_NUMERIC_INTEGER);
    addModelField("org.test.Employee",
                  "name",
                  String.class.getName(),
                  DataType.TYPE_STRING);
    addModelField("org.test.Employee",
                  "bigAbsence",
                  Boolean.class.getName(),
                  DataType.TYPE_BOOLEAN);
    addModelField("org.test.Bonus",
                  "this",
                  "org.test.Bonus",
                  DataType.TYPE_THIS);
    addModelField("org.test.Bonus",
                  "amount",
                  Double.class.getName(),
                  DataType.TYPE_NUMERIC_DOUBLE);
    addModelField("org.test.Bonus",
                  "employee",
                  "org.test.Employee",
                  DataType.TYPE_OBJECT);
    final GuidedDecisionTableGeneratorListener listener = new GuidedDecisionTableGeneratorListener(result,
                                                                                                   dmo);
    listeners.add(listener);
    //Convert
    final ExcelParser parser = new ExcelParser(listeners);
    final InputStream is = this.getClass().getResourceAsStream("GUVNOR-2888.xlsx");
    try {
        parser.parseFile(is);
    } finally {
        try {
            is.close();
        } catch (IOException ioe) {
            fail(ioe.getMessage());
        }
    }
    //Check conversion results
    assertEquals(1,
                 result.getMessages().size());
    assertTrue(result.getMessages().get(0).getMessage().contains("I13"));
    //Check basics
    final List<GuidedDecisionTable52> dtables = listener.getGuidedDecisionTables();
    assertNotNull(dtables);
    assertEquals(1,
                 dtables.size());
    GuidedDecisionTable52 dtable = dtables.get(0);
    assertEquals("bonus_program",
                 dtable.getTableName());
    assertEquals(GuidedDecisionTable52.TableFormat.EXTENDED_ENTRY,
                 dtable.getTableFormat());
    //Check expanded columns
    List<BaseColumn> columns = dtable.getExpandedColumns();
    assertNotNull(columns);
    assertEquals(12,
                 columns.size());
    assertTrue(columns.get(0) instanceof RowNumberCol52);
    assertTrue(columns.get(1) instanceof RuleNameColumn);
    assertTrue(columns.get(2) instanceof DescriptionCol52);
    assertTrue(columns.get(3) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(4) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(5) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(6) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(7) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(8) instanceof BRLConditionVariableColumn);
    assertTrue(columns.get(9) instanceof BRLActionVariableColumn);
    assertTrue(columns.get(10) instanceof BRLActionVariableColumn);
    assertTrue(columns.get(11) instanceof BRLActionVariableColumn);
    //Check individual condition columns
    assertEquals(3,
                 dtable.getConditions().size());
    //Pattern 0
    assertTrue(dtable.getConditions().get(0) instanceof BRLConditionColumn);
    BRLConditionColumn conditionCol0 = ((BRLConditionColumn) dtable.getConditions().get(0));
    assertEquals("Converted from ['Served between', 'Served between', 'Served more', 'absence']",
                 conditionCol0.getHeader());
    assertEquals(4,
                 conditionCol0.getChildColumns().size());
    List<IPattern> conditionCol0definition = conditionCol0.getDefinition();
    assertEquals(1,
                 conditionCol0definition.size());
    assertTrue(conditionCol0definition.get(0) instanceof FactPattern);
    FactPattern conditionCol0fp = (FactPattern) conditionCol0definition.get(0);
    assertEquals("Employee",
                 conditionCol0fp.getFactType());
    assertEquals(4,
                 conditionCol0fp.getNumberOfConstraints());
    //Pattern 0 - Field Constraint 0
    assertTrue(conditionCol0fp.getConstraint(0) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol0fpsfc0 = (SingleFieldConstraint) conditionCol0fp.getConstraint(0);
    assertEquals("yearsOfService",
                 conditionCol0fpsfc0.getFieldName());
    assertEquals(">=",
                 conditionCol0fpsfc0.getOperator());
    assertEquals("param1",
                 conditionCol0fpsfc0.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol0fpsfc0.getConstraintValueType());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0fpsfc0.getFieldType());
    //Pattern 0 - Field Constraint 0 - Variable 0
    BRLConditionVariableColumn conditionCol0param0 = conditionCol0.getChildColumns().get(0);
    assertEquals("param1",
                 conditionCol0param0.getVarName());
    assertEquals("Served between",
                 conditionCol0param0.getHeader());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0param0.getFieldType());
    assertEquals("Employee",
                 conditionCol0param0.getFactType());
    assertEquals("yearsOfService",
                 conditionCol0param0.getFactField());
    //Pattern 0 - Field Constraint 1
    assertTrue(conditionCol0fp.getConstraint(1) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol0fpsfc1 = (SingleFieldConstraint) conditionCol0fp.getConstraint(1);
    assertEquals("yearsOfService",
                 conditionCol0fpsfc1.getFieldName());
    assertEquals("<",
                 conditionCol0fpsfc1.getOperator());
    assertEquals("param2",
                 conditionCol0fpsfc1.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol0fpsfc1.getConstraintValueType());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0fpsfc1.getFieldType());
    //Pattern 0 - Field Constraint 1 - Variable 0
    BRLConditionVariableColumn conditionCol0param1 = conditionCol0.getChildColumns().get(1);
    assertEquals("param2",
                 conditionCol0param1.getVarName());
    assertEquals("Served between",
                 conditionCol0param1.getHeader());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0param1.getFieldType());
    assertEquals("Employee",
                 conditionCol0param1.getFactType());
    assertEquals("yearsOfService",
                 conditionCol0param1.getFactField());
    //Pattern 0 - Field Constraint 2
    assertTrue(conditionCol0fp.getConstraint(2) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol0fpsfc2 = (SingleFieldConstraint) conditionCol0fp.getConstraint(2);
    assertEquals("yearsOfService",
                 conditionCol0fpsfc2.getFieldName());
    assertEquals(">",
                 conditionCol0fpsfc2.getOperator());
    assertEquals("param3",
                 conditionCol0fpsfc2.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol0fpsfc2.getConstraintValueType());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0fpsfc2.getFieldType());
    //Pattern 0 - Field Constraint 2 - Variable 0
    BRLConditionVariableColumn conditionCol0param2 = conditionCol0.getChildColumns().get(2);
    assertEquals("param3",
                 conditionCol0param2.getVarName());
    assertEquals("Served more",
                 conditionCol0param2.getHeader());
    assertEquals(DataType.TYPE_NUMERIC_INTEGER,
                 conditionCol0param2.getFieldType());
    assertEquals("Employee",
                 conditionCol0param2.getFactType());
    assertEquals("yearsOfService",
                 conditionCol0param2.getFactField());
    //Pattern 0 - Field Constraint 3
    assertTrue(conditionCol0fp.getConstraint(3) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol0fpsfc3 = (SingleFieldConstraint) conditionCol0fp.getConstraint(3);
    assertEquals("bigAbsence",
                 conditionCol0fpsfc3.getFieldName());
    assertEquals("==",
                 conditionCol0fpsfc3.getOperator());
    assertEquals("param4",
                 conditionCol0fpsfc3.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol0fpsfc3.getConstraintValueType());
    assertEquals(DataType.TYPE_BOOLEAN,
                 conditionCol0fpsfc3.getFieldType());
    //Pattern 0 - Field Constraint 3 - Variable 0
    BRLConditionVariableColumn conditionCol0param3 = conditionCol0.getChildColumns().get(3);
    assertEquals("param4",
                 conditionCol0param3.getVarName());
    assertEquals("absence",
                 conditionCol0param3.getHeader());
    assertEquals(DataType.TYPE_BOOLEAN,
                 conditionCol0param3.getFieldType());
    assertEquals("Employee",
                 conditionCol0param3.getFactType());
    assertEquals("bigAbsence",
                 conditionCol0param3.getFactField());
    //Pattern 1
    assertTrue(dtable.getConditions().get(1) instanceof BRLConditionColumn);
    BRLConditionColumn conditionCol1 = ((BRLConditionColumn) dtable.getConditions().get(1));
    assertEquals("Converted from ['bonus for employee']",
                 conditionCol1.getHeader());
    assertEquals(1,
                 conditionCol1.getChildColumns().size());
    List<IPattern> conditionCol1definition = conditionCol1.getDefinition();
    assertEquals(1,
                 conditionCol1definition.size());
    assertTrue(conditionCol1definition.get(0) instanceof FactPattern);
    FactPattern conditionCol1fp = (FactPattern) conditionCol1definition.get(0);
    assertEquals("Bonus",
                 conditionCol1fp.getFactType());
    assertEquals(1,
                 conditionCol1fp.getNumberOfConstraints());
    //Pattern 1 - Field Constraint 0
    assertTrue(conditionCol1fp.getConstraint(0) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol1fpsfc0 = (SingleFieldConstraint) conditionCol1fp.getConstraint(0);
    assertEquals("employee",
                 conditionCol1fpsfc0.getFieldName());
    assertEquals("==",
                 conditionCol1fpsfc0.getOperator());
    assertEquals("param5",
                 conditionCol1fpsfc0.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol1fpsfc0.getConstraintValueType());
    assertEquals(DataType.TYPE_OBJECT,
                 conditionCol1fpsfc0.getFieldType());
    //Pattern 1 - Field Constraint 0 - Variable 0
    BRLConditionVariableColumn conditionCol1param0 = conditionCol1.getChildColumns().get(0);
    assertEquals("param5",
                 conditionCol1param0.getVarName());
    assertEquals("bonus for employee",
                 conditionCol1param0.getHeader());
    assertEquals(DataType.TYPE_OBJECT,
                 conditionCol1param0.getFieldType());
    assertEquals("Bonus",
                 conditionCol1param0.getFactType());
    assertEquals("employee",
                 conditionCol1param0.getFactField());
    //Pattern 2
    assertTrue(dtable.getConditions().get(2) instanceof BRLConditionColumn);
    BRLConditionColumn conditionCol2 = ((BRLConditionColumn) dtable.getConditions().get(2));
    assertEquals("Converted from ['no bonus for employee']",
                 conditionCol2.getHeader());
    assertEquals(1,
                 conditionCol2.getChildColumns().size());
    List<IPattern> conditionCol2definition = conditionCol2.getDefinition();
    assertEquals(1,
                 conditionCol2definition.size());
    assertTrue(conditionCol2definition.get(0) instanceof CompositeFactPattern);
    CompositeFactPattern conditionCol2cfp = (CompositeFactPattern) conditionCol2definition.get(0);
    assertEquals(CompositeFactPattern.COMPOSITE_TYPE_NOT,
                 conditionCol2cfp.getType());
    assertEquals(1,
                 conditionCol2cfp.getPatterns().length);
    assertTrue(conditionCol2cfp.getPatterns()[0] instanceof FactPattern);
    FactPattern conditionCol2fp = (FactPattern) conditionCol2cfp.getPatterns()[0];
    assertEquals("Bonus",
                 conditionCol2fp.getFactType());
    assertEquals(1,
                 conditionCol2fp.getNumberOfConstraints());
    //Pattern 2 - Field Constraint 0
    assertTrue(conditionCol2fp.getConstraint(0) instanceof SingleFieldConstraint);
    final SingleFieldConstraint conditionCol2fpsfc0 = (SingleFieldConstraint) conditionCol2fp.getConstraint(0);
    assertEquals("employee",
                 conditionCol2fpsfc0.getFieldName());
    assertEquals("==",
                 conditionCol2fpsfc0.getOperator());
    assertEquals("param6",
                 conditionCol2fpsfc0.getValue());
    assertEquals(SingleFieldConstraint.TYPE_TEMPLATE,
                 conditionCol2fpsfc0.getConstraintValueType());
    assertEquals(DataType.TYPE_OBJECT,
                 conditionCol2fpsfc0.getFieldType());
    //Pattern 2 - Field Constraint 0 - Variable 0
    BRLConditionVariableColumn conditionCol2param0 = conditionCol2.getChildColumns().get(0);
    assertEquals("param6",
                 conditionCol2param0.getVarName());
    assertEquals("no bonus for employee",
                 conditionCol2param0.getHeader());
    assertEquals(DataType.TYPE_OBJECT,
                 conditionCol2param0.getFieldType());
    assertEquals("Bonus",
                 conditionCol2param0.getFactType());
    assertEquals("employee",
                 conditionCol2param0.getFactField());
    //Check individual action columns
    assertEquals(3,
                 dtable.getActionCols().size());
    //Action 0
    assertTrue(dtable.getActionCols().get(0) instanceof BRLActionColumn);
    BRLActionColumn actionCol0 = ((BRLActionColumn) dtable.getActionCols().get(0));
    assertEquals("Converted from ['Inser bonus of amount']",
                 actionCol0.getHeader());
    assertEquals(1,
                 actionCol0.getChildColumns().size());
    List<IAction> actionCol0definition = actionCol0.getDefinition();
    assertEquals(1,
                 actionCol0definition.size());
    assertTrue(actionCol0definition.get(0) instanceof FreeFormLine);
    FreeFormLine actionCol0ffl0 = (FreeFormLine) actionCol0definition.get(0);
    assertEquals("Bonus $b = new Bonus(); $b.setAmount((double)@{param7}); $b.setEmployee($e); insert($b);",
                 actionCol0ffl0.getText());
    //Action 0 - Variable 0
    BRLActionVariableColumn actionCol0param0 = actionCol0.getChildColumns().get(0);
    assertEquals("param7",
                 actionCol0param0.getVarName());
    assertEquals("Inser bonus of amount",
                 actionCol0param0.getHeader());
    assertEquals(DataType.TYPE_OBJECT,
                 actionCol0param0.getFieldType());
    //Action 1
    BRLActionColumn actionCol1 = ((BRLActionColumn) dtable.getActionCols().get(1));
    assertEquals("Converted from ['retract']",
                 actionCol1.getHeader());
    assertEquals(1,
                 actionCol1.getChildColumns().size());
    List<IAction> actionCol1definition = actionCol1.getDefinition();
    assertEquals(1,
                 actionCol1definition.size());
    assertTrue(actionCol1definition.get(0) instanceof ActionRetractFact);
    ActionRetractFact actionCol1arf = (ActionRetractFact) actionCol1definition.get(0);
    assertEquals("$bonus",
                 actionCol1arf.getVariableName());
    assertTrue(dtable.getActionCols().get(1) instanceof BRLActionColumn);
    //Action 1 - Variable 0
    BRLActionVariableColumn actionCol1param0 = actionCol1.getChildColumns().get(0);
    assertEquals("param8",
                 actionCol1param0.getVarName());
    assertEquals("retract",
                 actionCol1param0.getHeader());
    assertEquals(DataType.TYPE_BOOLEAN,
                 actionCol1param0.getFieldType());
    //Action 2
    BRLActionColumn actionCol2 = ((BRLActionColumn) dtable.getActionCols().get(2));
    assertEquals("Converted from ['retract2']",
                 actionCol2.getHeader());
    assertEquals(1,
                 actionCol2.getChildColumns().size());
    List<IAction> actionCol2definition = actionCol2.getDefinition();
    assertEquals(1,
                 actionCol2definition.size());
    assertTrue(actionCol2definition.get(0) instanceof ActionRetractFact);
    ActionRetractFact actionCol2arf = (ActionRetractFact) actionCol2definition.get(0);
    assertEquals("$b",
                 actionCol2arf.getVariableName());
    assertTrue(dtable.getActionCols().get(2) instanceof BRLActionColumn);
    //Action 2 - Variable 1
    BRLActionVariableColumn actionCol2param0 = actionCol2.getChildColumns().get(0);
    assertEquals("",
                 actionCol2param0.getVarName());
    assertEquals("retract2",
                 actionCol2param0.getHeader());
    assertEquals(DataType.TYPE_BOOLEAN,
                 actionCol2param0.getFieldType());
    //Check data
    assertEquals(4,
                 dtable.getData().size());
    assertTrue(isRowEquivalent(new Object[]{1, "", "Lowest bonus", 0, 2, null, false, "", "$e", "400", false, false},
                               dtable.getData().get(0)));
    assertTrue(isRowEquivalent(new Object[]{2, "", "Middle bonus", 2, 6, null, false, "", "$e", "800", false, false},
                               dtable.getData().get(1)));
    assertTrue(isRowEquivalent(new Object[]{3, "", "High bonus", null, null, 6, false, "", "", "1000", false, false},
                               dtable.getData().get(2)));
    assertTrue(isRowEquivalent(new Object[]{4, "", "Big absence", null, null, null, true, "$e", "", "", true, true},
                               dtable.getData().get(3)));
}