Revision: 17565
          http://sourceforge.net/p/gate/code/17565
Author:   johann_p
Date:     2014-03-06 14:59:10 +0000 (Thu, 06 Mar 2014)
Log Message:
-----------
Add a utility method to resolve variables of the
form ${name} or $env{name} in Strings against
various kinds of sources for the variable values.

Modified Paths:
--------------
    gate/trunk/src/main/gate/Utils.java

Modified: gate/trunk/src/main/gate/Utils.java
===================================================================
--- gate/trunk/src/main/gate/Utils.java 2014-03-06 14:53:16 UTC (rev 17564)
+++ gate/trunk/src/main/gate/Utils.java 2014-03-06 14:59:10 UTC (rev 17565)
@@ -18,6 +18,7 @@
 import gate.annotation.AnnotationSetImpl;
 import gate.creole.ConditionalSerialController;
 import gate.creole.RunningStrategy;
+import gate.util.FeatureBearer;
 import gate.util.GateRuntimeException;
 import gate.util.InvalidOffsetException;
 import gate.util.OffsetComparator;
@@ -1010,4 +1011,159 @@
     }
   }
   
+  /**
+   * This will replace all occurrences of variables of the form $env{name}, 
+   * $prop{name}, $doc{featname}, $pr_parm{inputAS} or $$env{name} etc in a 
String.
+   * 
+   * The source for replacing the variable can be  environment variables,
+   * system properties, or arbitrary maps or resources specified when calling
+   * the method.
+   * <p>
+   * Examples:
+   * <ul>
+   * <li><code>replaceVariablesInString("text $env{GATE_HOME} more 
text")</code>:
+   * returns "text /path/to/gate more text" if the environment variable 
+   * "GATE_HOME" was set to "/path/to/gate"
+   * <li><code>replaceVariablesInString("text $pr{myfeature1} more 
text",pr1)</code>:
+   * returns "myvalue1" if the feature map of the processing resource pr1 
+   * contains an entry with key "myfeature" and value "myvalue"
+   * <li><code>replaceVariablesInString("text ${somekey} more 
text",map1,map2,resource1,map3)</code>:
+   *  this will
+   * find the value of an entry with key "somekey" in the first Map object 
specified
+   * in the parameter list of the method.
+   * </ul>
+   * <p>
+   * The possible sources for finding values for a variable are:
+   * <ul>
+   * <li><code>System.getenv()</code>: for variables of the form $env{name}
+   * <li><code>System.getProperties()</code>: for variables of the form 
$prop{name}
+   * <li><code>Resource</code>: the feature map of any resource which is 
specified in the 
+   * list of objects is used for variables of the form $resource{name} or 
+   * for variables of the form $corpus{name} if the resource is a corpus, for
+   * $pr{name} if the resource is a processing resource and so on. If the 
+   * resource is a processing resource its 
+   * <li><code>FeatureMap</code> or <code>Map</code>: any feature map or 
+   * Map which can be used to look up String keys can be specified
+   * as a source and will be used for variables of the form ${name}.
+   * </ul>
+   * <p>
+   * The value substituted is converted to a string using the toString() 
+   * method of whatever object is stored in the map. If the value returned
+   * by Map.get(key) is null, no substitution is carried out and the 
+   * variable is left unchanged in the string.
+   * <p>
+   * The following variable constructs are supported:
+   * <ul>
+   * <li>$env{name} will be replaced with the value from the environment 
variables map 
+   * from System.getenv() and nothing else.
+   * <li>$prop{name} will be replaced with the value of the properties map 
+   * from System.getProperties() and nothing else.
+   * <li>$controller{name} will be replaced with the value of a feature from 
the FeatureMap
+   * of the first resource of type Controller found in the argument list.
+   * <li>$corpus{name} will be replaced with the value of a feature from the 
FeatureMap
+   * of the first resource of type Corpus found in the argument list.
+   * <li>$pr{name} will be replaced with the value of a feature from the 
FeatureMap
+   * of the first resource of type ProcessingResource found in the argument 
list.
+   * <li>$pr_parm{name} will be replaced with the value of the parameter 'name'
+   * of the first resource of type ProcessingResource found in the argument 
list.
+   * This can be especially useful to replace a variable in one parameter with
+   * the value of another, potentially hidden, parameter of the same PR.
+   * <li>$doc{name} will be replaced with the value of a feature from the 
FeatureMap
+   * of the first resource of type Document found in the argument list.
+   * <li>$resource{name} will be replaced with the value of a feature from the 
FeatureMap
+   * of the first resource of type Resource found in the argument list.
+   * </ul>
+   * <p>
+   * If two dollar characters are used instead of one, the replacement string
+   * will in turn be subject to replacement, e.g. $$env{abc} could get replaced
+   * with the replacement string '$corpus{f1}' which would in turn get replaced
+   * with the value of the feature 'f1' from the feature set of the first 
+   * corpus in the parameter list that has a value for that feature.
+   *  
+   */
+  public static String replaceVariablesInString(
+          String string, Object... sources)
+  {
+    Matcher matcher = 
Pattern.compile("(\\$\\$?)([a-zA-Z]*)\\{([^}]+)\\}").matcher(string);
+    int findFrom = 0;
+    int lastEnd = 0;
+    StringBuilder sb = new StringBuilder(string.length()*2);
+    while(findFrom < string.length() && matcher.find(findFrom)) {
+      String dollars = matcher.group(1);
+      String type = matcher.group(2);
+      String varname = matcher.group(3);
+      int matchStart = matcher.start();
+      // whenever we have found something, we can immediately move the part
+      // from the last end of match to the new start of match to the 
+      // return string, that is just unmodified string ...
+      // But only if the length is > 0
+      if((matchStart - lastEnd) > 0) {
+        sb.append(string.substring(lastEnd,matchStart));
+      }
+      lastEnd = matcher.end();
+      Object value = null;
+      // for each match we find, go through all the sources in the order
+      // listed and if the type of the source matches the requested type
+      // then try to look the variable up. If we find something use it and
+      // finish looking, otherwise continue until all sources have been 
+      // exhausted. 
+      // A variable where no value has been found anywhere is not replaced.
+      // If a variable got replaced and it was a variable that started with
+      // two dollar signs, then the replacement value is first getting 
+      // recursively replaced too.
+      if(type.equals("env")) {
+        value = System.getenv().get(varname);
+      } else if(type.equals("prop")) {
+        value = System.getProperties().get(varname);
+      } else {
+        for(Object source : sources) {
+          if(type.isEmpty()) { // an empty variable type matches only maps 
from the sources
+            if(source instanceof Map) {
+              value = ((Map)source).get(varname);
+            }
+          } else if(type.equals("pr") && (source instanceof 
ProcessingResource)) {
+            value = ((FeatureBearer)source).getFeatures().get(varname);
+          } else if(type.equals("pr_parm") && (source instanceof 
ProcessingResource)) {
+            try {
+              value = ((ProcessingResource)source).getParameterValue(varname);
+            } catch(Exception ex) {
+              // do nothing, leave the value null
+            }
+          } else if(type.equals("doc") && (source instanceof Document)) {
+            value = ((FeatureBearer)source).getFeatures().get(varname);
+          } else if(type.equals("controller") && (source instanceof 
Controller)) {
+            value = ((FeatureBearer)source).getFeatures().get(varname);
+          } else if(type.equals("corpus") && (source instanceof Corpus)) {
+            value = ((FeatureBearer)source).getFeatures().get(varname);
+          } else if(type.equals("resource") && (source instanceof Resource)) {
+            value = ((FeatureBearer)source).getFeatures().get(varname);
+          }
+          if(value != null) {
+            break;
+          }
+        } // for source : sources
+      }
+      // only do anything at all if we found a value for this parameter
+      if(value != null) {
+        String replacement = value.toString();
+        // if we had double-dollars, first do the recursive replacement ...
+        if(dollars.equals("$$")) {
+          replacement = replaceVariablesInString(replacement, sources);
+        }
+        sb.append(replacement);
+      } else {
+        sb.append(matcher.group());
+        // the first character after the match
+      }
+      findFrom = matcher.end();
+    } // while matcher.find ...
+    // if we have some unmatched string left over, append it too
+    if(lastEnd < string.length()) {
+      sb.append(string.substring(lastEnd));
+    }
+    return sb.toString();    
+  }
+  
+  
+  
 }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Subversion Kills Productivity. Get off Subversion & Make the Move to Perforce.
With Perforce, you get hassle-free workflows. Merge that actually works. 
Faster operations. Version large binaries.  Built-in WAN optimization and the
freedom to use Git, Perforce or both. Make the move to Perforce.
http://pubads.g.doubleclick.net/gampad/clk?id=122218951&iu=/4140/ostg.clktrk
_______________________________________________
GATE-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gate-cvs

Reply via email to