You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by jo...@apache.org on 2011/08/01 16:21:35 UTC

svn commit: r1152792 [2/10] - in /uima/sandbox/trunk/TextMarker: org.apache.uima.tm.textruler.lp2/ org.apache.uima.tm.textruler.lp2/META-INF/ org.apache.uima.tm.textruler.lp2/bin/ org.apache.uima.tm.textruler.lp2/src/ org.apache.uima.tm.textruler.lp2/s...

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,337 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.Type;
+import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.tm.textruler.core.TextRulerAnnotation;
+import org.apache.uima.tm.textruler.core.TextRulerExample;
+import org.apache.uima.tm.textruler.core.TextRulerRule;
+import org.apache.uima.tm.textruler.core.TextRulerRuleItem;
+import org.apache.uima.tm.textruler.core.TextRulerRulePattern;
+import org.apache.uima.tm.textruler.core.TextRulerTarget;
+import org.apache.uima.tm.textruler.core.TextRulerToolkit;
+import org.apache.uima.tm.textruler.core.TextRulerTarget.MLTargetType;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2ContextConstraint;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2OtherConstraint;
+import org.apache.uima.util.FileUtils;
+
+public class NaiveLP2 extends BasicLP2 {
+
+  public NaiveLP2(String inputDir, String prePropTMFile, String tmpDir, String[] slotNames,
+          Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+    super(inputDir, prePropTMFile, tmpDir, slotNames, filterSet, delegate);
+  }
+
+  public static final boolean SAVE_DEBUG_INFO_IN_TEMPFOLDER = false;
+
+  @Override
+  protected void induceRulesFromExample(TextRulerExample e, int roundNumber) {
+    LP2Rule baseRule = createInitialRuleForPositiveExample(e);
+    List<LP2Rule> genRules = generalizeRule(baseRule);
+
+    if (shouldAbort())
+      return;
+
+    List<LP2Rule> test = new ArrayList<LP2Rule>();
+
+    // int i=1;
+    // for (LP2Rule newRule : genRules)
+    // {
+    // if (shouldAbort())
+    // return;
+    // sendStatusUpdateToDelegate("Round "+roundNumber+" - Testing proposed generalization "+i+"/"+(genRules.size())+
+    // "    - uncovered examples: "+
+    // (examples.size()-coveredExamples.size() + " / "+examples.size()),
+    // TextRulerLearnerState.ML_RUNNING, false);
+    // i++;
+    // testRuleOnDocumentSet(newRule, exampleDocuments);
+    //
+    // checkAndHandleNewRule(newRule);
+    //			
+    // if (TextRulerToolkit.DEBUG)
+    // test.add(newRule);
+    // }
+    // new cache and testCAS optimized rule testing:
+
+    sendStatusUpdateToDelegate("Round " + roundNumber + " - Testing " + (genRules.size())
+            + "generalizations... - uncovered examples: "
+            + (examples.size() - coveredExamples.size() + " / " + examples.size()),
+            TextRulerLearnerState.ML_RUNNING, false);
+    testRulesOnDocumentSet(new ArrayList<TextRulerRule>(genRules), exampleDocuments);
+
+    for (LP2Rule newRule : genRules) {
+      checkAndHandleNewRule(newRule);
+      if (TextRulerToolkit.DEBUG)
+        test.add(newRule);
+    }
+
+    if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+      Collections.sort(test, new Comparator<LP2Rule>() {
+
+        public int compare(LP2Rule o1, LP2Rule o2) {
+          return o1.getRuleString().compareTo(o2.getRuleString());
+        }
+
+      });
+
+      String startend = e.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY ? "left_"
+              : "right_";
+      File file = new File(tempDirectory() + startend + "generalizations" + roundNumber + ".tm");
+      StringBuffer str = new StringBuffer();
+      for (TextRulerRule rule : test) {
+        str.append(rule.getCoveringStatistics() + "\t\t" + rule.getRuleString() + "\n");
+      }
+      try {
+        FileUtils.saveString2File(str.toString(), file);
+      } catch (Exception ex) {
+        ex.printStackTrace();
+      }
+    }
+
+  }
+
+  protected void checkAndHandleNewRule(LP2Rule rule) {
+    boolean tooFewPositives = rule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+    boolean tooManyErrors = rule.getErrorRate() > maxErrorThreshold;
+
+    boolean isBestRule = !(tooFewPositives || tooManyErrors);
+
+    if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+      TextRulerToolkit.appendStringToFile(tempDirectory() + "bestcandidates.tm", rule
+              .getRuleString()
+              + "\n");
+
+    if (isBestRule) {
+      currentBestRules.add(rule);
+      currentBestRules.removeSubsumedRules();
+      currentBestRules.cutToMaxSize();
+    } else if (!tooFewPositives) {
+
+      // test in context
+      // in our TM representation, we simply can add a NEAR condition in
+      // the MARKing rule item and retest it on the
+      // corpus. we should do that for all kinds of tags we have, but
+      // currently we only do it for the corresponding opening/closing
+      // tag, since we do not have any information about other slots yet!
+      // // TODO use all other slot tags! (see optimized version as well)
+
+      if (true) {
+        rule = rule.copy();
+        LP2RuleItem item = rule.getMarkingRuleItem();
+        // TextRulerToolkit.log("CONTEXTUAL RULE CANDIDATE: "+rule.getRuleString()+"  ;  "+rule.getCoveringStatistics());
+        item.setContextConstraint(new MLLP2ContextConstraint(slotMaximumTokenCount, rule));
+        rule.setIsContextualRule(true);
+
+        rule.setNeedsCompile(true);
+
+        if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+          TextRulerToolkit.appendStringToFile(tempDirectory() + "ctxcandidates.tm", rule
+                  .getRuleString());
+
+        testRuleOnDocumentSet(rule, exampleDocuments); // not very
+        // fast... but
+        // works!
+        boolean ctxTooFewPositives = rule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+        boolean ctxTooManyErrors = rule.getErrorRate() > maxErrorThreshold;
+        boolean isGoodContextRule = !(ctxTooFewPositives || ctxTooManyErrors);
+        if (isGoodContextRule) {
+          currentContextualRules.add(rule);
+          currentContextualRules.removeSubsumedRules();
+          currentContextualRules.cutToMaxSize();
+        }
+      }
+
+    }
+  }
+
+  protected List<LP2Rule> generalizeRule(LP2Rule baseRule) {
+    List<LP2Rule> result = new ArrayList<LP2Rule>();
+    TextRulerRulePattern rulePattern = new TextRulerRulePattern();
+    TextRulerRulePattern prePattern = baseRule.getPreFillerPattern();
+
+    for (int i = prePattern.size() - 1; i >= 0; i--) // we have to reverse
+    // the order again!
+    {
+      rulePattern.add(prePattern.get(i));
+    }
+    rulePattern.addAll(baseRule.getPostFillerPattern());
+
+    recursiveGeneralizeRule(baseRule, rulePattern, new TextRulerRulePattern(), result);
+    TextRulerToolkit.log("GENERALIZATIONS: " + result.size());
+
+    for (LP2Rule r : result)
+      removeOutermostWildCardItemsFromRule(r);
+
+    // for (LP2Rule r : result)
+    // {
+    // TextRulerToolkit.log("NEWRULE = "+r.getRuleString());
+    // }
+
+    return result;
+  }
+
+  protected LP2Rule createInitialRuleForPositiveExample(TextRulerExample example) {
+    TextRulerTarget target = example.getTarget();
+    LP2Rule rule = new LP2Rule(this, example.getTarget());
+    CAS docCas = example.getDocumentCAS();
+    TextRulerAnnotation exampleAnnotation = example.getAnnotation();
+    TypeSystem ts = docCas.getTypeSystem();
+    Type tokensRootType = ts.getType(TextRulerToolkit.TM_ANY_TYPE_NAME);
+    int thePosition = target.type == MLTargetType.SINGLE_LEFT_BOUNDARY ? exampleAnnotation
+            .getBegin() : exampleAnnotation.getEnd();
+
+    List<AnnotationFS> leftContext = TextRulerToolkit.getAnnotationsBeforePosition(docCas,
+            thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+                    filterSet), tokensRootType);
+    List<AnnotationFS> rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas,
+            thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+                    filterSet), tokensRootType);
+
+    // the left context has to be reversed since we get the arrayList from
+    // the slot's point of view!
+    for (int i = leftContext.size() - 1; i >= 0; i--) {
+      TextRulerAnnotation annot = new TextRulerAnnotation(leftContext.get(i), example.getDocument());
+      LP2RuleItem item = new LP2RuleItem();
+      item.setWordConstraint(annot);
+      if (item.getWordConstraint().isRegExpConstraint())
+        item.addOtherConstraint(new MLLP2OtherConstraint(annot, annot));
+      rule.addPreFillerItem(item);
+    }
+
+    for (AnnotationFS afs : rightContext) {
+      TextRulerAnnotation annot = new TextRulerAnnotation(afs, example.getDocument());
+      LP2RuleItem item = new LP2RuleItem();
+      item.setWordConstraint(annot);
+      if (item.getWordConstraint().isRegExpConstraint())
+        item.addOtherConstraint(new MLLP2OtherConstraint(annot, annot));
+
+      rule.addPostFillerItem(item);
+    }
+    TextRulerToolkit.log("INITIAL RULE: " + rule.getRuleString());
+    return rule;
+  }
+
+  protected void recursiveGeneralizeRule(LP2Rule baseRule, TextRulerRulePattern allItems,
+          TextRulerRulePattern currentPattern, List<LP2Rule> resultList) {
+    if (currentPattern.size() == allItems.size()) {
+      // create new Rule
+      LP2Rule newRule = new LP2Rule(this, baseRule.getTarget());
+      int preCount = baseRule.getPreFillerPattern().size();
+      for (int i = 0; i < currentPattern.size(); i++) {
+        if (i < preCount)
+          newRule.addPreFillerItem(currentPattern.get(i));
+        else
+          newRule.addPostFillerItem(currentPattern.get(i));
+      }
+      // TextRulerToolkit.log("GEN: "+newRule.getRuleString());
+      if (newRule.totalInnerConstraintCount() > 0) // skip the ANY ANY ANY
+        // ANY... rule ! this
+        // makes no sense in no
+        // application!!
+        resultList.add(newRule);
+    } else {
+      int index = currentPattern.size();
+      TextRulerRuleItem baseItem = allItems.get(index);
+      List<TextRulerRuleItem> itemGeneralizations = generalizeRuleItem((LP2RuleItem) baseItem);
+      for (TextRulerRuleItem newItem : itemGeneralizations) {
+        currentPattern.add(newItem);
+        recursiveGeneralizeRule(baseRule, allItems, currentPattern, resultList);
+        currentPattern.remove(currentPattern.size() - 1);
+      }
+    }
+  }
+
+  protected void recursiveGeneralizeRuleItem(LP2RuleItem baseItem,
+          List<MLLP2OtherConstraint> otherConstraints, int currentConstraintIndex,
+          List<MLLP2OtherConstraint> currentConstraintTuple, List<TextRulerRuleItem> result) {
+    if (currentConstraintIndex > otherConstraints.size() - 1) {
+      LP2RuleItem newItem;
+      newItem = new LP2RuleItem();
+      for (MLLP2OtherConstraint c : currentConstraintTuple)
+        newItem.addOtherConstraint(c.copy());
+      result.add(newItem);
+    } else {
+      MLLP2OtherConstraint currentConstraint = otherConstraints.get(currentConstraintIndex);
+      // recurse WITH and WITHOUT this key:
+      recursiveGeneralizeRuleItem(baseItem, otherConstraints, currentConstraintIndex + 1,
+              currentConstraintTuple, result);
+      currentConstraintTuple.add(currentConstraint);
+      recursiveGeneralizeRuleItem(baseItem, otherConstraints, currentConstraintIndex + 1,
+              currentConstraintTuple, result);
+      currentConstraintTuple.remove(currentConstraintTuple.size() - 1);
+    }
+  }
+
+  protected List<TextRulerRuleItem> generalizeRuleItem(LP2RuleItem baseItem) {
+    List<TextRulerRuleItem> result = new ArrayList<TextRulerRuleItem>();
+
+    // one with word constraint
+    if (baseItem.getWordConstraint() != null) {
+      LP2RuleItem newItem = new LP2RuleItem();
+      newItem.setWordConstraint(baseItem.getWordConstraint().copy());
+      result.add(newItem);
+    }
+
+    // all other combinations without word constraint
+    // List<String> keys = new
+    // ArrayList<String>(baseItem.getOtherConstraints().keySet());
+    List<MLLP2OtherConstraint> constraints = baseItem.getOtherConstraints();
+    recursiveGeneralizeRuleItem(baseItem, constraints, 0, new ArrayList<MLLP2OtherConstraint>(),
+            result);
+    return result;
+  }
+
+  protected void removeOutermostWildCardItemsFromRule(LP2Rule rule) {
+    while (true) {
+      LP2RuleItem item = (LP2RuleItem) rule.getOutermostPreFillerItem();
+      if (item == null) // no more items left
+        break;
+
+      // if this rule is a RIGHT BOUNDARY rule, we must not remove the
+      // last remaining pre filler item,
+      // since this is used for marking the SLOT END BOUNDARY (= RIGHT
+      // BOUNDARY)
+      if ((rule.getTarget().type == MLTargetType.SINGLE_RIGHT_BOUNDARY)
+              && (rule.getPreFillerPattern().size() == 1))
+        break;
+
+      if (item.totalConstraintCount() == 0)
+        rule.removeOutermostPreFillerItem();
+      else
+        break;
+    }
+    while (true) {
+      LP2RuleItem item = (LP2RuleItem) rule.getOutermostPostFillerItem();
+      if (item == null) // no more items left
+        break;
+
+      // if this rule is a LEFT BOUNDARY rule, we must not remove the last
+      // remaining post filler item,
+      // since this is used for marking the SLOT START BOUNDARY (= LEFT
+      // BOUNDARY)
+      if ((rule.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY)
+              && (rule.getPostFillerPattern().size() == 1))
+        break;
+
+      if (item.totalConstraintCount() == 0)
+        rule.removeOutermostPostFillerItem();
+      else
+        break;
+    }
+  }
+
+  @Override
+  public boolean collectNegativeCoveredInstancesWhenTesting() {
+    return false;
+  }
+
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,53 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.tm.textruler.extension.TextRulerLearner;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter.MLAlgorithmParamType;
+
+public class NaiveLP2Factory implements TextRulerLearnerFactory {
+
+  public TextRulerLearner createAlgorithm(String inputFolderPath, String additionalFolderPath,
+          String prePropTMFile, String tempFolderPath, String[] fullSlotTypeNames,
+          Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+    return new NaiveLP2(inputFolderPath, prePropTMFile, tempFolderPath, fullSlotTypeNames,
+            filterSet, delegate);
+  }
+
+  public TextRulerLearnerParameter[] getAlgorithmParameters() {
+    TextRulerLearnerParameter[] result = new TextRulerLearnerParameter[5];
+
+    result[0] = new TextRulerLearnerParameter(BasicLP2.WINDOW_SIZE_KEY,
+            "Context Window Size (to the left and right)", MLAlgorithmParamType.ML_INT_PARAM);
+    result[1] = new TextRulerLearnerParameter(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+            "Best Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+    result[2] = new TextRulerLearnerParameter(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+            "Minimum Covered Positives per Rule", MLAlgorithmParamType.ML_INT_PARAM);
+    result[3] = new TextRulerLearnerParameter(BasicLP2.MAX_ERROR_THRESHOLD_KEY,
+            "Maximum Error Threshold", MLAlgorithmParamType.ML_FLOAT_PARAM);
+    result[4] = new TextRulerLearnerParameter(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+            "Contextual Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+
+    return result;
+  }
+
+  public Map<String, Object> getAlgorithmParameterStandardValues() {
+    Map<String, Object> result = new HashMap<String, Object>();
+    result.put(BasicLP2.WINDOW_SIZE_KEY, BasicLP2.STANDARD_WINDOW_SIZE);
+    result
+            .put(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+                    BasicLP2.STANDARD_MAX_CURRENT_BEST_RULES_COUNT);
+    result.put(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+            BasicLP2.STANDARD_MIN_COVERED_POSITIVES_PER_RULE);
+    result.put(BasicLP2.MAX_ERROR_THRESHOLD_KEY, BasicLP2.STANDARD_MAX_ERROR_THRESHOLD);
+    result.put(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+            BasicLP2.STANDARD_MAX_CONTEXTUAL_RULES_COUNT);
+    return result;
+  }
+
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,104 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.uima.tm.textruler.TextRulerPlugin;
+import org.apache.uima.tm.textruler.extension.TextRulerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class NaiveLP2PreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+  public static String ID = "org.apache.uima.tm.textruler.algorithmPages";
+
+  private TextRulerLearnerController algorithmController;
+
+  private IPreferenceStore store;
+
+  private ArrayList<FieldEditor> fields = new ArrayList<FieldEditor>();
+
+  public NaiveLP2PreferencePage() {
+    TextRulerLearnerController ctrl = TextRulerController.getControllerForID("org.apache.uima.tm.textruler.lp2naive");
+    this.algorithmController = ctrl;
+    store = TextRulerPlugin.getDefault().getPreferenceStore();
+    setPreferenceStore(store);
+  }
+  
+  @Override
+  protected Control createContents(Composite parent) {
+    Composite top = new Composite(parent, SWT.LEFT);
+    top.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+    top.setLayout(new GridLayout());
+    
+    TextRulerLearnerFactory f = algorithmController.getFactory();
+    TextRulerLearnerParameter[] params = f.getAlgorithmParameters();
+    Map<String, Object> values = f.getAlgorithmParameterStandardValues();
+    if (params != null) {
+      for (int i = 0; i < params.length; i++) {
+        TextRulerLearnerParameter p = params[i];
+        String id = algorithmController.getID() + "." + p.id;
+        FieldEditor l = null;
+        switch (p.type) {
+          case ML_BOOL_PARAM: {
+            l = new BooleanFieldEditor(id, p.name, top);
+            fields.add(l);
+            store.setDefault(id, (Boolean) values.get(p.id));
+            l.setPreferenceStore(store);
+            l.load();
+            break;
+          }
+
+          case ML_FLOAT_PARAM:
+          case ML_INT_PARAM:
+          case ML_STRING_PARAM: {
+            l = new StringFieldEditor(id, p.name, top);
+            fields.add(l);
+            store.setDefault(id, values.get(p.id).toString());
+            l.setPreferenceStore(store);
+            l.load();
+            break;
+          }
+          case ML_SELECT_PARAM:
+            break;
+        }
+      }
+    }
+    return top;
+  }
+  
+  @Override
+  public void init(IWorkbench workbench) { 
+  }
+
+  @Override
+  protected void performDefaults() {
+    for (FieldEditor f : fields)
+      f.loadDefault();
+    // super.performDefaults();
+  }
+
+  @Override
+  public boolean performOk() {
+    for (FieldEditor f : fields)
+      f.store();
+    // return super.performOk();
+    return true;
+  }
+
+  
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,572 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.Type;
+import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.tm.textruler.core.TextRulerAnnotation;
+import org.apache.uima.tm.textruler.core.TextRulerExample;
+import org.apache.uima.tm.textruler.core.TextRulerRule;
+import org.apache.uima.tm.textruler.core.TextRulerRuleList;
+import org.apache.uima.tm.textruler.core.TextRulerStatisticsCollector;
+import org.apache.uima.tm.textruler.core.TextRulerTarget;
+import org.apache.uima.tm.textruler.core.TextRulerToolkit;
+import org.apache.uima.tm.textruler.core.TextRulerTarget.MLTargetType;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2ContextConstraint;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2OtherConstraint;
+import org.apache.uima.util.FileUtils;
+
+
+public class OptimizedLP2 extends BasicLP2 {
+
+  public static final boolean SAVE_DEBUG_INFO_IN_TEMPFOLDER = false;
+
+  private Map<String, TextRulerStatisticsCollector> cachedTestedStartRuleStatistics = new HashMap<String, TextRulerStatisticsCollector>();
+
+  private long cachedTestedStartRuleStatisticsHitCounter = 0;
+
+  public OptimizedLP2(String inputDir, String prePropTMFile, String tmpDir, String[] slotNames,
+          Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+    super(inputDir, prePropTMFile, tmpDir, slotNames, filterSet, delegate);
+  }
+
+  @Override
+  protected TextRulerRuleList learnTaggingRules(TextRulerTarget target,
+          TextRulerRuleList contextualRules) {
+    cachedTestedStartRuleStatisticsHitCounter = 0;
+    cachedTestedStartRuleStatistics.clear();
+    TextRulerRuleList result = super.learnTaggingRules(target, contextualRules);
+    TextRulerToolkit
+            .log("[OptimizedLP2.learnTaggingRules] saved rule testings due to start rule results cache: "
+                    + cachedTestedStartRuleStatisticsHitCounter);
+    TextRulerToolkit.log("[OptimizedLP2.learnTaggingRules] cacheSize at end of induction: "
+            + cachedTestedStartRuleStatistics.size());
+    cachedTestedStartRuleStatistics.clear();
+    return result;
+  }
+
+  @Override
+  protected void induceRulesFromExample(final TextRulerExample e, final int roundNumber) {
+    // in order to get cache optimized contextual start rules testing, we
+    // simply create
+    // and add the ctxStartRules HERE (not when we want to create a
+    // contextual rule!) to
+    // all startRules, test those startRules + ctxStartRules cacheOptimized
+    // on the trainings-Set
+    // and then have their results in our covering-statistics-cache for
+    // later ctx rules creation!
+    List<LP2Rule> startRules = createStartRulesForExample(e);
+    if (startRules.size() < 1)
+      return;
+    List<LP2Rule> ctxStartRules = new ArrayList<LP2Rule>();
+    // TODO set isCorrectionRuleMode = true ?!
+    if (!(e.getTarget().isLeftCorrection() || e.getTarget().isRightCorrection()))
+      ctxStartRules = createContextStartRulesForStartRule(startRules.get(0));
+    List<LP2Rule> rulesToTest = new ArrayList<LP2Rule>(ctxStartRules.size() + startRules.size());
+    rulesToTest.addAll(startRules);
+    rulesToTest.addAll(ctxStartRules);
+
+    sendStatusUpdateToDelegate("Round " + roundNumber + " - Testing " + rulesToTest.size()
+            + " start rules... " + " - uncovered examples: "
+            + (examples.size() - coveredExamples.size() + " / " + examples.size()) + " cs: "
+            + cachedTestedStartRuleStatistics.size(), TextRulerLearnerState.ML_RUNNING, false);
+    testStartRulesIfNotCached(rulesToTest);
+    if (shouldAbort())
+      return;
+    // int i=0;
+    // for (LP2Rule r : startRules)
+    // {
+    // i++;
+    // sendStatusUpdateToDelegate("Round "+roundNumber+" - Testing start rule "+i+"/"+startRules.size()+
+    // "     - uncovered examples: "+
+    // (examples.size()-coveredExamples.size() + " / "+examples.size())+
+    // "cs:"+cachedTestedStartRuleStatistics.size(),
+    // TextRulerLearnerState.ML_RUNNING, false);
+    // testStartRuleIfNotCached(r);
+    // if (shouldAbort())
+    // return;
+    // if (TextRulerToolkit.DEBUG)
+    // {
+    // if
+    // (!r.getCoveringStatistics().getCoveredPositiveExamples().contains(e))
+    // {
+    // TextRulerToolkit.log("A START RULE MUST (!) COVER ITs POSITIVE EXAMPLE! OTHEREWISE, THERE IS SOMETHING WRONG!!");
+    // }
+    // }
+    // }
+
+    Comparator<LP2Rule> cmp = new Comparator<LP2Rule>() {
+
+      public int compare(LP2Rule o1, LP2Rule o2) {
+        return o1.getCoveringStatistics().getCoveredPositivesCount()
+                - o2.getCoveringStatistics().getCoveredPositivesCount();
+      }
+
+    };
+    // sort from low to high positive coverage in order to higher the
+    // pruning probability while recursion:
+    Collections.sort(startRules, cmp);
+    Collections.sort(ctxStartRules, cmp);
+
+    while ((startRules.size() > 0)
+            && (startRules.get(0).getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives))
+      startRules.remove(0);
+
+    while ((ctxStartRules.size() > 0)
+            && (ctxStartRules.get(0).getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives))
+      ctxStartRules.remove(0);
+
+    sendStatusUpdateToDelegate("Round " + roundNumber + " - Creating all generalizations..."
+            + "     - uncovered examples: "
+            + (examples.size() - coveredExamples.size() + " / " + examples.size()),
+            TextRulerLearnerState.ML_RUNNING, false);
+
+    // only for debugging purposes: List<LP2Rule> resultRules = new
+    // ArrayList<LP2Rule>();
+
+    ArrayList<LP2Rule> debugRuleCollector = null;
+
+    if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+      debugRuleCollector = new ArrayList<LP2Rule>();
+    }
+
+    if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, 0, new ArrayList<LP2Rule>(),
+            null, debugRuleCollector))
+      return; // aborted!
+
+    if (TextRulerToolkit.DEBUG && debugRuleCollector != null && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+      // TextRulerToolkit.log("all combinations: "+debugRuleCollector.size());
+
+      Collections.sort(debugRuleCollector, new Comparator<LP2Rule>() {
+
+        public int compare(LP2Rule o1, LP2Rule o2) {
+          return o1.getRuleString().compareTo(o2.getRuleString());
+        }
+
+      });
+      String startend = e.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY ? "left_"
+              : "right_";
+      File file = new File(tempDirectory() + startend + "generalizations" + roundNumber + ".tm");
+      StringBuffer str = new StringBuffer();
+      for (TextRulerRule rule : debugRuleCollector) {
+        str.append(rule.getCoveringStatistics() + "\t\t" + rule.getRuleString() + "\n");
+      }
+      try {
+        FileUtils.saveString2File(str.toString(), file);
+      } catch (Exception ex) {
+        ex.printStackTrace();
+      }
+      // TextRulerToolkit.log("----");
+    }
+  }
+
+  protected void testStartRulesIfNotCached(List<LP2Rule> startRules) {
+    List<TextRulerRule> rulesToTest = new ArrayList<TextRulerRule>();
+
+    for (LP2Rule r : startRules) {
+      String key = r.getRuleString();
+      if (cachedTestedStartRuleStatistics.containsKey(key)) {
+        r.setCoveringStatistics(cachedTestedStartRuleStatistics.get(key).copy());
+        cachedTestedStartRuleStatisticsHitCounter++;
+      } else
+        rulesToTest.add(r);
+    }
+
+    if (rulesToTest.size() > 0) {
+      testRulesOnDocumentSet(rulesToTest, exampleDocuments);
+      if (shouldAbort())
+        return;
+      for (TextRulerRule r : rulesToTest) {
+        String key = r.getRuleString();
+        cachedTestedStartRuleStatistics.put(key, r.getCoveringStatistics().copy());
+      }
+    }
+  }
+
+  protected LP2Rule combineRulesToOneRule(List<LP2Rule> ruleList,
+          TextRulerStatisticsCollector covering) {
+    // TextRulerToolkit.log("----------------------------------------------");
+    // for (LP2Rule r : ruleList)
+    // TextRulerToolkit.log(r+" ; "+r.getCoveringStatistics());
+
+    LP2Rule rule = new LP2Rule(this, ruleList.get(0).getTarget());
+
+    int maxPreCount = 0;
+    int maxPostCount = 0;
+    for (LP2Rule r : ruleList) {
+      if (r.getPreFillerPattern().size() > maxPreCount)
+        maxPreCount = r.getPreFillerPattern().size();
+      if (r.getPostFillerPattern().size() > maxPostCount)
+        maxPostCount = r.getPostFillerPattern().size();
+    }
+
+    for (int i = 0; i < maxPreCount; i++) {
+      LP2RuleItem newItem = new LP2RuleItem();
+      for (LP2Rule r : ruleList)
+        if (i < r.getPreFillerPattern().size()) {
+          LP2RuleItem rItem = (LP2RuleItem) r.getPreFillerPattern().get(
+                  r.getPreFillerPattern().size() - i - 1);
+          if (rItem.getWordConstraint() != null)
+            newItem.setWordConstraint(rItem.getWordConstraint().copy());
+          if (rItem.getContextConstraint() != null)
+            newItem.setContextConstraint(rItem.getContextConstraint().copy());
+          // for (String key : rItem.getOtherConstraints().keySet())
+          // newItem.setOtherConstraint(key,
+          // rItem.getOtherConstraints().get(key).copy());
+          for (MLLP2OtherConstraint c : rItem.getOtherConstraints())
+            newItem.addOtherConstraint(c.copy());
+
+        }
+      rule.addPreFillerItem(newItem);
+    }
+
+    for (int i = 0; i < maxPostCount; i++) {
+      LP2RuleItem newItem = new LP2RuleItem();
+      for (LP2Rule r : ruleList)
+        if (i < r.getPostFillerPattern().size()) {
+          LP2RuleItem rItem = (LP2RuleItem) r.getPostFillerPattern().get(i);
+          if (rItem.getWordConstraint() != null)
+            newItem.setWordConstraint(rItem.getWordConstraint().copy());
+          if (rItem.getContextConstraint() != null)
+            newItem.setContextConstraint(rItem.getContextConstraint().copy());
+          // for (String key : rItem.getOtherConstraints().keySet())
+          // newItem.setOtherConstraint(key,
+          // rItem.getOtherConstraints().get(key).copy());
+          for (MLLP2OtherConstraint c : rItem.getOtherConstraints())
+            newItem.addOtherConstraint(c.copy());
+        }
+      rule.addPostFillerItem(newItem);
+    }
+
+    rule.setCoveringStatistics(covering.copy());
+
+    return rule;
+  }
+
+  protected boolean recursiveCreateAllRuleCombinations(final List<LP2Rule> startRules,
+          final List<LP2Rule> ctxStartRules, final int index, final List<LP2Rule> currentRuleTuple,
+          final TextRulerStatisticsCollector currentCovering, final List<LP2Rule> debugRuleCollector) {
+    if (index > startRules.size() - 1) {
+      if (shouldAbort())
+        return false;
+      if (currentRuleTuple.size() > 0) {
+        LP2Rule newRule = createAndCheckRuleFromStartRules(currentRuleTuple, currentCovering,
+                ctxStartRules);
+        if (debugRuleCollector != null)
+          debugRuleCollector.add(newRule);
+      }
+    } else {
+      // recurse WITHOUT and WITH this start rule:
+      if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, index + 1,
+              currentRuleTuple, currentCovering, debugRuleCollector))
+        return false;
+
+      // only recurse WITH this rule, if the constraint it adds does
+      // really create a new rule!
+      // if a word constraint of the same item is already present, we do
+      // not need to add any other constraint of that
+      // token, since it does not make sense to add more constraints to
+      // the obviously most specific rule !
+
+      LP2Rule candidateRule = startRules.get(index);
+      boolean isPre = candidateRule.isPreFillerStartRule();
+      boolean containsWordConstraint = false;
+      for (LP2Rule r : currentRuleTuple)
+        if (r.isPreFillerStartRule() == isPre) {
+          if (isPre)
+            containsWordConstraint = r.getPreFillerPattern().size() == candidateRule
+                    .getPreFillerPattern().size();
+          else
+            containsWordConstraint = r.getPostFillerPattern().size() == candidateRule
+                    .getPostFillerPattern().size();
+          if (containsWordConstraint)
+            break;
+        }
+      if (!containsWordConstraint) {
+        // and calculate intersection of coverings:
+        TextRulerStatisticsCollector newCovering;
+        if (currentCovering != null)
+          newCovering = getCoveringIntersection(currentCovering, candidateRule
+                  .getCoveringStatistics());
+        else
+          newCovering = candidateRule.getCoveringStatistics();
+
+        // prune all rules that go below our minCoveredPositives
+        // threshold!
+        if (newCovering.getCoveredPositivesCount() >= minCoveredPositives) {
+          // add rule to configuration tuple
+          currentRuleTuple.add(candidateRule);
+
+          if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, index + 1,
+                  currentRuleTuple, newCovering, debugRuleCollector))
+            return false;
+          currentRuleTuple.remove(currentRuleTuple.size() - 1);
+        }
+      }
+    }
+    return true;
+  }
+
+  protected TextRulerStatisticsCollector getCoveringIntersection(
+          final TextRulerStatisticsCollector c1, final TextRulerStatisticsCollector c2) {
+    // calculate intersections of coverings:
+    TextRulerStatisticsCollector resultC = new TextRulerStatisticsCollector(c1);
+
+    resultC.getCoveredPositiveExamples().retainAll(c2.getCoveredPositiveExamples());
+    resultC.getCoveredNegativeExamples().retainAll(c2.getCoveredNegativeExamples());
+    resultC.reflectCountsFromCoveredExamples();
+
+    return resultC;
+  }
+
+  protected LP2Rule createAndCheckRuleFromStartRules(final List<LP2Rule> startRules,
+          final TextRulerStatisticsCollector covering, final List<LP2Rule> ctxStartRules) {
+    LP2Rule newRule = combineRulesToOneRule(startRules, covering);
+    // TextRulerToolkit.log("COMBINED RULE: "+newRule.getRuleString()+" ; "+newRule.getCoveringStatistics());
+    boolean tooFewPositives = newRule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+    boolean tooManyErrors = newRule.getErrorRate() > maxErrorThreshold;
+    boolean isBestRule = !(tooFewPositives || tooManyErrors);
+
+    if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+      TextRulerToolkit.appendStringToFile(tempDirectory() + "bestcandidates.tm", newRule
+              .getRuleString()
+              + "\n");
+
+    if (isBestRule) {
+      currentBestRules.add(newRule);
+      currentBestRules.removeSubsumedRules();
+      currentBestRules.cutToMaxSize();
+    } else if (!tooFewPositives && (ctxStartRules.size() > 0)) {
+      // new: use precalculated ctx startrules:
+      for (LP2Rule ctxStartRule : ctxStartRules) {
+
+        MLLP2ContextConstraint ctxConstraint = ctxStartRule.getMarkingRuleItem()
+                .getContextConstraint();
+        LP2Rule newCTXRule = newRule.copy();
+        newCTXRule.setIsContextualRule(true);
+        newCTXRule.getMarkingRuleItem().setContextConstraint(ctxConstraint.copy());
+        newCTXRule.setNeedsCompile(true);
+        newCTXRule.compileRuleString();
+        newCTXRule.setCoveringStatistics(getCoveringIntersection(newRule.getCoveringStatistics(),
+                ctxStartRule.getCoveringStatistics()));
+        // if
+        // (newCTXRule.getCoveringStatistics().getCoveredPositivesCount()
+        // < 1)
+        // {
+        // TextRulerToolkit.log("ERROR!");
+        // }
+
+        boolean ctxTooFewPositives = newCTXRule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+        boolean ctxTooManyErrors = newCTXRule.getErrorRate() > maxErrorThreshold;
+        boolean isGoodCTXRule = !(ctxTooFewPositives || ctxTooManyErrors);
+        // TextRulerToolkit.log("CTXRULE :  "+newCTXRule.getRuleString()
+        // + " ; "+newCTXRule.getCoveringStatistics());
+
+        if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+          TextRulerToolkit.appendStringToFile(tempDirectory() + "ctxcandidates.tm", newCTXRule
+                  .getRuleString()
+                  + "\n");
+
+        if (isGoodCTXRule) {
+          currentContextualRules.add(newCTXRule);
+          currentContextualRules.removeSubsumedRules();
+          currentContextualRules.cutToMaxSize();
+        }
+      }
+    }
+
+    return newRule;
+  }
+
+  protected LP2Rule createStartRuleForConstraint(final TextRulerTarget target,
+          final int contextSize, final boolean isLeftContext, final LP2RuleItem constraintItem) {
+    LP2Rule newRule = new LP2Rule(this, target);
+
+    // add contextSize-1 ANY items
+    for (int j = 0; j < contextSize - 1; j++)
+      if (isLeftContext)
+        newRule.addPreFillerItem(new LP2RuleItem());
+      else
+        newRule.addPostFillerItem(new LP2RuleItem());
+
+    // add 1 constraint item:
+    if (isLeftContext)
+      newRule.addPreFillerItem(constraintItem);
+    else
+      newRule.addPostFillerItem(constraintItem);
+
+    // if we are building the left context start rules for LEFT BOUNDARIES,
+    // we need at least ONE
+    // empty ANY item as the marking item:
+    if (isLeftContext
+            && (target.type == MLTargetType.SINGLE_LEFT_BOUNDARY || target.type == MLTargetType.SINGLE_LEFT_CORRECTION))
+      newRule.addPostFillerItem(new LP2RuleItem());
+    // otherwise, if we build the right context rules for RIGHT BOUNDARY
+    // RULES, we need at least ONE
+    // empty ANY item on the LEFT as the marking item:
+    else if (!isLeftContext
+            && (target.type == MLTargetType.SINGLE_RIGHT_BOUNDARY || target.type == MLTargetType.SINGLE_RIGHT_CORRECTION))
+      newRule.addPreFillerItem(new LP2RuleItem());
+
+    newRule.setIsPreFillerStartRule(isLeftContext);
+    // if (isLeftContext)
+    // newRule.setStartRuleItemIndex(0);
+    // else
+    // newRule.setStartRuleItemIndex(newRule.getPreFillerPattern().size()+newRule.getPostFillerPattern().size()-1);
+    return newRule;
+  }
+
+  protected List<LP2Rule> createContextStartRulesForStartRule(final LP2Rule aStartRule) {
+    List<LP2Rule> result = new ArrayList<LP2Rule>();
+
+    // TODO make all other tags contextual tags here. for now we take only
+    // the counterpart
+    // tag of the current learning process: (opening/closing tags)
+
+    LP2RuleItem ctxItem = new LP2RuleItem();
+    MLLP2ContextConstraint ctxConstraint = new MLLP2ContextConstraint(slotMaximumTokenCount,
+            aStartRule);
+    ctxItem.setContextConstraint(ctxConstraint);
+    LP2Rule ctxStartRule = new LP2Rule(this, aStartRule.getTarget());
+    ctxStartRule.setIsContextualRule(true);
+    if (aStartRule.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY)
+      ctxStartRule.addPostFillerItem(ctxItem);
+    else
+      ctxStartRule.addPreFillerItem(ctxItem);
+    result.add(ctxStartRule);
+    return result;
+  }
+
+  protected List<LP2Rule> createStartRulesForExample(final TextRulerExample example) {
+    TextRulerTarget target = example.getTarget();
+    List<LP2Rule> result = new ArrayList<LP2Rule>();
+    CAS docCas = example.getDocumentCAS();
+    TextRulerAnnotation exampleAnnotation = example.getAnnotation();
+    TypeSystem ts = docCas.getTypeSystem();
+    Type tokensRootType = ts.getType(TextRulerToolkit.TM_ANY_TYPE_NAME);
+
+    boolean isLeftBoundary = (target.type == MLTargetType.SINGLE_LEFT_BOUNDARY || target.type == MLTargetType.SINGLE_LEFT_CORRECTION);
+    int thePosition = isLeftBoundary ? exampleAnnotation.getBegin() : exampleAnnotation.getEnd();
+    List<AnnotationFS> leftContext = TextRulerToolkit.getAnnotationsBeforePosition(docCas,
+            thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+                    filterSet), tokensRootType);
+
+    List<AnnotationFS> rightContext;
+    if (target.type == MLTargetType.SINGLE_LEFT_CORRECTION
+            || target.type == MLTargetType.SINGLE_RIGHT_CORRECTION) {
+      rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas, thePosition,
+              windowSize + 1, TextRulerToolkit.getFilterSetWithSlotNames(slotNames, filterSet),
+              tokensRootType);
+      rightContext.remove(0);
+    } else {
+      rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas, thePosition, windowSize,
+              TextRulerToolkit.getFilterSetWithSlotNames(slotNames, filterSet), tokensRootType);
+    }
+
+    int totalCount = leftContext.size() + rightContext.size();
+
+    // LEFT CONTEXT (PRE FILLER PATTERN)
+    // result.add(createStartRuleForConstraint(example, 0, true, null));
+
+    for (int index = 0; index < totalCount; index++) {
+      boolean isPre = index < leftContext.size();
+      int prePostIndex = isPre ? index : index - leftContext.size();
+      AnnotationFS tokenAFS = isPre ? leftContext.get(leftContext.size() - 1 - prePostIndex)
+              : rightContext.get(prePostIndex);
+      TextRulerAnnotation tokenAnnotation = new TextRulerAnnotation(tokenAFS, example.getDocument());
+      LP2RuleItem wordItem = new LP2RuleItem();
+
+      // one rule with only the word constraint:
+      wordItem.setWordConstraint(tokenAnnotation);
+      result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+              wordItem));
+
+      if (wordItem.getWordConstraint().isRegExpConstraint()) {
+        LP2RuleItem basicItem = new LP2RuleItem();
+        // basicItem.setOtherConstraint("basicTM", new
+        // MLLP2OtherConstraint(tokenAnnotation, tokenAnnotation));
+        basicItem.addOtherConstraint(new MLLP2OtherConstraint(tokenAnnotation, tokenAnnotation));
+        result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+                basicItem));
+      }
+
+      // // POS-Tags created by our test hmm tagger.
+      // Type posTagsRootType = ts.getType("de.uniwue.ml.ML.postag");
+      // if (posTagsRootType != null)
+      // {
+      // List<AnnotationFS> posTagAnnotations =
+      // TextRulerToolkit.getAnnotationsWithinBounds(example.getDocumentCAS(),
+      // tokenAnnotation.getBegin(), tokenAnnotation.getEnd(), null,
+      // posTagsRootType);
+      // if (posTagAnnotations.size()>0)
+      // {
+      // if (TextRulerToolkit.DEBUG && posTagAnnotations.size()>1)
+      // {
+      // TextRulerToolkit.logIfDebug("HOW CAN ONE TOKEN HAVE MORE THAN ONE POS TAG ?? "+tokenAnnotation.getBegin()+":"+tokenAnnotation.getEnd()+"="+tokenAnnotation.getCoveredText());
+      // for (AnnotationFS afs : posTagAnnotations)
+      // {
+      // System.out.print(afs.getType().getShortName()+":"+afs.getCoveredText()+" "+afs.getBegin()+":"+afs.getEnd()+"\n");
+      // }
+      // TextRulerToolkit.logIfDebug("");
+      // }
+      //					
+      // TextRulerAnnotation posTagAnnotation = new
+      // TextRulerAnnotation(posTagAnnotations.get(0),
+      // example.getDocument());
+      // LP2RuleItem basicItem = new LP2RuleItem();
+      // basicItem.setOtherConstraint("postag", new
+      // MLLP2OtherConstraint(posTagAnnotation, posTagAnnotation));
+      // result.add(createStartRuleForConstraint(example.getTarget(),
+      // prePostIndex+1, isPre, basicItem));
+      // }
+      // }
+
+      // new dynamic system: grab everything we get from the annotation
+      // index that lies over this token:
+      // (annotations WITHIN (with smaller bounds than the token itself)
+      // are ignored for now! we could
+      // add using them with the CONTAINS constraint. but our
+      // MLLP2OtherConstraint is not yet capable of this!
+
+      List<AnnotationFS> featureAnnotations = TextRulerToolkit.getNonTMAnnoationsOverToken(docCas,
+              tokenAFS, filterSetWithSlotNames);
+      if (TextRulerToolkit.DEBUG && featureAnnotations.size() > 1) {
+        TextRulerToolkit.log("FOUND MORE THAN ONE EXTRA TOKEN FEATURE ANNOTATION !");
+        for (AnnotationFS featA : featureAnnotations)
+          TextRulerToolkit.log(featA.toString());
+        TextRulerToolkit.log("--------------------------------");
+      }
+      for (AnnotationFS featA : featureAnnotations) {
+        TextRulerAnnotation featureAnnot = new TextRulerAnnotation(featA, example.getDocument());
+        LP2RuleItem basicItem = new LP2RuleItem();
+        basicItem.addOtherConstraint(new MLLP2OtherConstraint(tokenAnnotation, featureAnnot));
+        result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+                basicItem));
+      }
+
+    }
+
+    // for (TextRulerRule r : result)
+    // {
+    // TextRulerToolkit.log("STARTRULE = "+r.getRuleString());
+    // }
+
+    return result;
+  }
+
+  @Override
+  public boolean collectNegativeCoveredInstancesWhenTesting() {
+    return true;
+  }
+
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,52 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.tm.textruler.extension.TextRulerLearner;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter.MLAlgorithmParamType;
+
+public class OptimizedLP2Factory implements TextRulerLearnerFactory {
+
+  public TextRulerLearner createAlgorithm(String inputFolderPath, String additionalFolderPath,
+          String prePropTMFile, String tempFolderPath, String[] fullSlotTypeNames,
+          Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+    return new OptimizedLP2(inputFolderPath, prePropTMFile, tempFolderPath, fullSlotTypeNames,
+            filterSet, delegate);
+  }
+
+  public TextRulerLearnerParameter[] getAlgorithmParameters() {
+    TextRulerLearnerParameter[] result = new TextRulerLearnerParameter[5];
+
+    result[0] = new TextRulerLearnerParameter(BasicLP2.WINDOW_SIZE_KEY,
+            "Context Window Size (to the left and right)", MLAlgorithmParamType.ML_INT_PARAM);
+    result[1] = new TextRulerLearnerParameter(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+            "Best Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+    result[2] = new TextRulerLearnerParameter(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+            "Minimum Covered Positives per Rule", MLAlgorithmParamType.ML_INT_PARAM);
+    result[3] = new TextRulerLearnerParameter(BasicLP2.MAX_ERROR_THRESHOLD_KEY,
+            "Maximum Error Threshold", MLAlgorithmParamType.ML_FLOAT_PARAM);
+    result[4] = new TextRulerLearnerParameter(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+            "Contextual Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+
+    return result;
+  }
+
+  public Map<String, Object> getAlgorithmParameterStandardValues() {
+    Map<String, Object> result = new HashMap<String, Object>();
+    result.put(BasicLP2.WINDOW_SIZE_KEY, BasicLP2.STANDARD_WINDOW_SIZE);
+    result
+            .put(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+                    BasicLP2.STANDARD_MAX_CURRENT_BEST_RULES_COUNT);
+    result.put(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+            BasicLP2.STANDARD_MIN_COVERED_POSITIVES_PER_RULE);
+    result.put(BasicLP2.MAX_ERROR_THRESHOLD_KEY, BasicLP2.STANDARD_MAX_ERROR_THRESHOLD);
+    result.put(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+            BasicLP2.STANDARD_MAX_CONTEXTUAL_RULES_COUNT);
+    return result;
+  }
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java Mon Aug  1 14:21:12 2011
@@ -0,0 +1,101 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.uima.tm.textruler.TextRulerPlugin;
+import org.apache.uima.tm.textruler.extension.TextRulerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class OptimizedLP2PreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+  public static String ID = "org.apache.uima.tm.textruler.algorithmPages";
+
+  private TextRulerLearnerController algorithmController;
+
+  private IPreferenceStore store;
+
+  private ArrayList<FieldEditor> fields = new ArrayList<FieldEditor>();
+
+  public OptimizedLP2PreferencePage() {
+    TextRulerLearnerController ctrl = TextRulerController.getControllerForID("org.apache.uima.tm.textruler.lp2opt");
+    this.algorithmController = ctrl;
+    store = TextRulerPlugin.getDefault().getPreferenceStore();
+    setPreferenceStore(store);
+  }
+  
+  @Override
+  protected Control createContents(Composite parent) {
+    Composite top = new Composite(parent, SWT.LEFT);
+    top.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+    top.setLayout(new GridLayout());
+    
+    TextRulerLearnerFactory f = algorithmController.getFactory();
+    TextRulerLearnerParameter[] params = f.getAlgorithmParameters();
+    Map<String, Object> values = f.getAlgorithmParameterStandardValues();
+    if (params != null) {
+      for (int i = 0; i < params.length; i++) {
+        TextRulerLearnerParameter p = params[i];
+        String id = algorithmController.getID() + "." + p.id;
+        FieldEditor l = null;
+        switch (p.type) {
+          case ML_BOOL_PARAM: {
+            l = new BooleanFieldEditor(id, p.name, top);
+            fields.add(l);
+            store.setDefault(id, (Boolean) values.get(p.id));
+            l.setPreferenceStore(store);
+            l.load();
+            break;
+          }
+
+          case ML_FLOAT_PARAM:
+          case ML_INT_PARAM:
+          case ML_STRING_PARAM: {
+            l = new StringFieldEditor(id, p.name, top);
+            fields.add(l);
+            store.setDefault(id, values.get(p.id).toString());
+            l.setPreferenceStore(store);
+            l.load();
+            break;
+          }
+          case ML_SELECT_PARAM:
+            break;
+        }
+      }
+    }
+    return top;
+  }
+  
+  @Override
+  public void init(IWorkbench workbench) { 
+  }
+
+  @Override
+  protected void performDefaults() {
+    for (FieldEditor f : fields)
+      f.loadDefault();
+    // super.performDefaults();
+  }
+
+  @Override
+  public boolean performOk() {
+    for (FieldEditor f : fields)
+      f.store();
+    // return super.performOk();
+    return true;
+  }
+}

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Aug  1 14:21:12 2011
@@ -0,0 +1 @@
+.settings

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath Mon Aug  1 14:21:12 2011
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project Mon Aug  1 14:21:12 2011
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.uima.tm.textruler.rapier</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF Mon Aug  1 14:21:12 2011
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: TextRuler Rapier Plugin
+Bundle-SymbolicName: org.apache.uima.tm.textruler.rapier;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.apache.uima.tm.textruler.rapier.RapierPlugin
+Bundle-Vendor: University of Würzburg
+Require-Bundle: org.eclipse.core.runtime,
+ org.apache.uima.tm.textruler,
+ org.apache.uima.runtime;bundle-version="2.3.0",
+ org.eclipse.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties Mon Aug  1 14:21:12 2011
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml Mon Aug  1 14:21:12 2011
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.apache.uima.tm.textruler.learners">
+      <learner
+            class="org.apache.uima.tm.textruler.rapier.RapierFactory"
+            id="org.apache.uima.tm.textruler.rapier"
+            name="RAPIER">
+      </learner>
+   </extension>
+   <extension
+         point="org.eclipse.ui.preferencePages">
+      <page
+            category="org.apache.uima.tm.textruler"
+            class="org.apache.uima.tm.textruler.rapier.RapierPreferencePage"
+            id="org.apache.uima.tm.textruler.rapier"
+            name="Rapier">
+      </page>
+   </extension>
+
+</plugin>

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain