lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gsing...@apache.org
Subject svn commit: r927178 - in /lucene/dev/trunk/lucene/contrib/benchmark: ./ conf/ src/java/org/apache/lucene/benchmark/byTask/tasks/ src/java/org/apache/lucene/benchmark/byTask/utils/
Date Wed, 24 Mar 2010 20:49:45 GMT
Author: gsingers
Date: Wed Mar 24 20:49:44 2010
New Revision: 927178

URL: http://svn.apache.org/viewvc?rev=927178&view=rev
Log:
LUCENE-2343: add support for benchmarking collectors

Added:
    lucene/dev/trunk/lucene/contrib/benchmark/conf/collector-small.alg
    lucene/dev/trunk/lucene/contrib/benchmark/conf/collector.alg
    lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java
  (with props)
Modified:
    lucene/dev/trunk/lucene/contrib/benchmark/CHANGES.txt
    lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
    lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Config.java

Modified: lucene/dev/trunk/lucene/contrib/benchmark/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/CHANGES.txt?rev=927178&r1=927177&r2=927178&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/contrib/benchmark/CHANGES.txt Wed Mar 24 20:49:44 2010
@@ -2,7 +2,10 @@ Lucene Benchmark Contrib Change Log
 
 The Benchmark contrib package contains code for benchmarking Lucene in a variety of ways.
 
-2/21/2020
+3/24/2010
+  LUCENE-2343: Added support for benchmarking collectors. (Grant Ingersoll, Shai Erera)
+
+2/21/2010
   LUCENE-2254: Add support to the quality package for running
   experiments with any combination of Title, Description, and Narrative.
   (Robert Muir)

Added: lucene/dev/trunk/lucene/contrib/benchmark/conf/collector-small.alg
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/conf/collector-small.alg?rev=927178&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/conf/collector-small.alg (added)
+++ lucene/dev/trunk/lucene/contrib/benchmark/conf/collector-small.alg Wed Mar 24 20:49:44
2010
@@ -0,0 +1,91 @@
+#/**
+# * Licensed to the Apache Software Foundation (ASF) under one or more
+# * contributor license agreements.  See the NOTICE file distributed with
+# * this work for additional information regarding copyright ownership.
+# * The ASF licenses this file to You under the Apache License, Version 2.0
+# * (the "License"); you may not use this file except in compliance with
+# * the License.  You may obtain a copy of the License at
+# *
+# *     http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# */
+# -------------------------------------------------------------------------------------
+# multi val params are iterated by NewRound's, added to reports, start with column name.
+
+# collector.class can be:
+#    Fully Qualified Class Name of a Collector with a empty constructor
+#    topScoreDocOrdered - Creates a TopScoreDocCollector that requires in order docs
+#    topScoreDocUnordered - Like above, but allows out of order
+collector.class=coll:topScoreDocOrdered:topScoreDocUnordered:topScoreDocOrdered:topScoreDocUnordered
+
+analyzer=org.apache.lucene.analysis.WhitespaceAnalyzer
+directory=FSDirectory
+#directory=RamDirectory
+
+doc.stored=true
+doc.tokenized=true
+doc.term.vector=false
+log.step=100000
+
+search.num.hits=100000
+
+content.source=org.apache.lucene.benchmark.byTask.feeds.LongToEnglishContentSource
+
+
+query.maker=org.apache.lucene.benchmark.byTask.feeds.LongToEnglishQueryMaker
+
+# task at this depth or less would print when they start
+task.max.depth.log=2
+
+log.queries=true
+# -------------------------------------------------------------------------------------
+
+{ "Rounds"
+
+    ResetSystemErase
+
+    { "Populate"
+        CreateIndex
+        { "MAddDocs" AddDoc } : 200000
+        Optimize
+        CloseIndex
+    }
+
+    OpenReader
+    { "topDocs" SearchWithCollector > : 10
+    CloseReader
+
+#    OpenReader
+#uses an array of search.num.hits size, but can also take in a parameter
+#    { "psc" SearchWithPostSortCollector > : 10
+#    { "psc100" SearchWithPostSortCollector(100) > : 10
+#    { "psc1000" SearchWithPostSortCollector(1000) > : 10
+#    { "psc10000" SearchWithPostSortCollector(10000) > : 10
+#    { "psc50000" SearchWithPostSortCollector(50000) > : 10
+#    CloseReader
+
+    RepSumByPref topDocs
+#    RepSumByPref psc
+#    RepSumByPref psc100
+#    RepSumByPref psc1000
+#    RepSumByPref psc10000
+#    RepSumByPref psc50000
+
+    NewRound
+
+} : 4
+
+#RepSumByNameRound
+#RepSumByName
+#RepSumByPrefRound topDocs
+#RepSumByPrefRound psc
+#RepSumByPrefRound psc100
+#RepSumByPrefRound psc1000
+#RepSumByPrefRound psc10000
+#RepSumByPrefRound psc50000
+

Added: lucene/dev/trunk/lucene/contrib/benchmark/conf/collector.alg
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/conf/collector.alg?rev=927178&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/conf/collector.alg (added)
+++ lucene/dev/trunk/lucene/contrib/benchmark/conf/collector.alg Wed Mar 24 20:49:44 2010
@@ -0,0 +1,91 @@
+#/**
+# * Licensed to the Apache Software Foundation (ASF) under one or more
+# * contributor license agreements.  See the NOTICE file distributed with
+# * this work for additional information regarding copyright ownership.
+# * The ASF licenses this file to You under the Apache License, Version 2.0
+# * (the "License"); you may not use this file except in compliance with
+# * the License.  You may obtain a copy of the License at
+# *
+# *     http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# */
+# -------------------------------------------------------------------------------------
+# multi val params are iterated by NewRound's, added to reports, start with column name.
+
+# collector.class can be:
+#    Fully Qualified Class Name of a Collector with a empty constructor
+#    topScoreDocOrdered - Creates a TopScoreDocCollector that requires in order docs
+#    topScoreDocUnordered - Like above, but allows out of order
+collector.class=coll:topScoreDocOrdered:topScoreDocUnordered:topScoreDocOrdered:topScoreDocUnordered
+
+analyzer=org.apache.lucene.analysis.WhitespaceAnalyzer
+directory=FSDirectory
+#directory=RamDirectory
+
+doc.stored=true
+doc.tokenized=true
+doc.term.vector=false
+log.step=100000
+
+search.num.hits=1000000
+
+content.source=org.apache.lucene.benchmark.byTask.feeds.LongToEnglishContentSource
+
+
+query.maker=org.apache.lucene.benchmark.byTask.feeds.LongToEnglishQueryMaker
+
+# task at this depth or less would print when they start
+task.max.depth.log=2
+
+log.queries=true
+# -------------------------------------------------------------------------------------
+
+{ "Rounds"
+
+    ResetSystemErase
+
+    { "Populate"
+        CreateIndex
+        { "MAddDocs" AddDoc } : 2000000
+        Optimize
+        CloseIndex
+    }
+
+    OpenReader
+    { "topDocs" SearchWithCollector > : 10
+    CloseReader
+
+#    OpenReader
+#uses an array of search.num.hits size, but can also take in a parameter
+#    { "psc" SearchWithPostSortCollector > : 10
+#    { "psc100" SearchWithPostSortCollector(100) > : 10
+#    { "psc1000" SearchWithPostSortCollector(1000) > : 10
+#    { "psc10000" SearchWithPostSortCollector(10000) > : 10
+#    { "psc50000" SearchWithPostSortCollector(50000) > : 10
+#    CloseReader
+
+    RepSumByPref topDocs
+#    RepSumByPref psc
+#    RepSumByPref psc100
+#    RepSumByPref psc1000
+#    RepSumByPref psc10000
+#    RepSumByPref psc50000
+
+    NewRound
+
+} : 4
+
+#RepSumByNameRound
+#RepSumByName
+#RepSumByPrefRound topDocs
+#RepSumByPrefRound psc
+#RepSumByPrefRound psc100
+#RepSumByPrefRound psc1000
+#RepSumByPrefRound psc10000
+#RepSumByPrefRound psc50000
+

Modified: lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java?rev=927178&r1=927177&r2=927178&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
(original)
+++ lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
Wed Mar 24 20:49:44 2010
@@ -30,10 +30,12 @@ import org.apache.lucene.benchmark.byTas
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.MultiTermQuery;
 import org.apache.lucene.search.TopFieldCollector;
 import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TopScoreDocCollector;
 import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -105,23 +107,29 @@ public abstract class ReadTask extends P
       res++;
       Query q = queryMaker.makeQuery();
       Sort sort = getSort();
-      TopDocs hits;
+      TopDocs hits = null;
       final int numHits = numHits();
       if (numHits > 0) {
-        if (sort != null) {
-          Weight w = q.weight(searcher);
-          TopFieldCollector collector = TopFieldCollector.create(sort, numHits,
-                                                                 true, withScore(),
-                                                                 withMaxScore(),
-                                                                 !w.scoresDocsOutOfOrder());
-          searcher.search(w, null, collector);
-          hits = collector.topDocs();
+        if (withCollector() == false) {
+          if (sort != null) {
+            Weight w = q.weight(searcher);
+            TopFieldCollector collector = TopFieldCollector.create(sort, numHits,
+                                                                   true, withScore(),
+                                                                   withMaxScore(),
+                                                                   !w.scoresDocsOutOfOrder());
+            searcher.search(w, null, collector);
+            hits = collector.topDocs();
+          } else {
+            hits = searcher.search(q, numHits);
+          }
         } else {
-          hits = searcher.search(q, numHits);
+          Collector collector = createCollector();
+          searcher.search(q, null, collector);
+          //hits = collector.topDocs();
         }
 
         final String printHitsField = getRunData().getConfig().get("print.hits.field", null);
-        if (printHitsField != null && printHitsField.length() > 0) {
+        if (hits != null && printHitsField != null && printHitsField.length()
> 0) {
           if (q instanceof MultiTermQuery) {
             System.out.println("MultiTermQuery term count = " + ((MultiTermQuery) q).getTotalNumberOfTerms());
           }
@@ -177,6 +185,9 @@ public abstract class ReadTask extends P
     return res;
   }
 
+  protected Collector createCollector() throws Exception {
+    return TopScoreDocCollector.create(numHits(), true);
+  }
 
 
   protected Document retrieveDoc(IndexReader ir, int id) throws IOException {
@@ -192,6 +203,10 @@ public abstract class ReadTask extends P
    * Return true if search should be performed.
    */
   public abstract boolean withSearch();
+
+  public boolean withCollector(){
+    return false;
+  }
   
 
   /**

Added: lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java?rev=927178&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java
(added)
+++ lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java
Wed Mar 24 20:49:44 2010
@@ -0,0 +1,95 @@
+package org.apache.lucene.benchmark.byTask.tasks;
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.benchmark.byTask.PerfRunData;
+import org.apache.lucene.benchmark.byTask.feeds.QueryMaker;
+import org.apache.lucene.benchmark.byTask.utils.Config;
+import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.TopScoreDocCollector;
+
+import java.io.IOException;
+
+/**
+ * Does search w/ a custom collector
+ */
+public class SearchWithCollectorTask extends SearchTask {
+
+  protected String clnName;
+
+  public SearchWithCollectorTask(PerfRunData runData) {
+    super(runData);
+  }
+
+  @Override
+  public void setup() throws Exception {
+    super.setup();
+    //check to make sure either the doc is being stored
+    PerfRunData runData = getRunData();
+    Config config = runData.getConfig();
+    clnName = config.get("collector.class", "");
+  }
+
+  
+
+  @Override
+  public boolean withCollector() {
+    return true;
+  }
+
+  @Override
+  protected Collector createCollector() throws Exception {
+    Collector collector = null;
+    if (clnName.equalsIgnoreCase("topScoreDocOrdered") == true) {
+      collector = TopScoreDocCollector.create(numHits(), true);
+    } else if (clnName.equalsIgnoreCase("topScoreDocUnOrdered") == true) {
+      collector = TopScoreDocCollector.create(numHits(), false);
+    } else if (clnName.length() > 0){
+      collector = Class.forName(clnName).asSubclass(Collector.class).newInstance();
+
+    } else {
+      collector = super.createCollector();
+    }
+    return collector;
+  }
+
+  @Override
+  public QueryMaker getQueryMaker() {
+    return getRunData().getQueryMaker(this);
+  }
+
+  @Override
+  public boolean withRetrieve() {
+    return false;
+  }
+
+  @Override
+  public boolean withSearch() {
+    return true;
+  }
+
+  @Override
+  public boolean withTraverse() {
+    return false;
+  }
+
+  @Override
+  public boolean withWarm() {
+    return false;
+  }
+
+}

Propchange: lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchWithCollectorTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Config.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Config.java?rev=927178&r1=927177&r2=927178&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Config.java
(original)
+++ lucene/dev/trunk/lucene/contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Config.java
Wed Mar 24 20:49:44 2010
@@ -22,20 +22,20 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.Reader;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Properties;
 import java.util.StringTokenizer;
 
 /**
  * Perf run configuration properties.
- * <p>
- * Numeric property containing ":", e.g. "10:100:5" is interpreted 
- * as array of numeric values. It is extracted once, on first use, and 
+ * <p/>
+ * Numeric property containing ":", e.g. "10:100:5" is interpreted
+ * as array of numeric values. It is extracted once, on first use, and
  * maintain a round number to return the appropriate value.
- * <p>
- * The config property "work.dir" tells where is the root of 
+ * <p/>
+ * The config property "work.dir" tells where is the root of
  * docs data dirs and indexes dirs. It is set to either of: <ul>
  * <li>value supplied for it in the alg file;</li>
  * <li>otherwise, value of System property "benchmark.work.dir";</li>
@@ -48,30 +48,31 @@ public class Config {
 
   private int roundNumber = 0;
   private Properties props;
-  private HashMap<String,Object> valByRound = new HashMap<String,Object>();
-  private HashMap<String,String> colForValByRound = new HashMap<String,String>();
+  private HashMap<String, Object> valByRound = new HashMap<String, Object>();
+  private HashMap<String, String> colForValByRound = new HashMap<String, String>();
   private String algorithmText;
 
   /**
    * Read both algorithm and config properties.
+   *
    * @param algReader from where to read algorithm and config properties.
    * @throws IOException
    */
-  public Config (Reader algReader) throws IOException {
+  public Config(Reader algReader) throws IOException {
     // read alg file to array of lines
     ArrayList<String> lines = new ArrayList<String>();
     BufferedReader r = new BufferedReader(algReader);
-    int lastConfigLine=0;
-    for (String line = r.readLine(); line!=null; line=r.readLine()) {
+    int lastConfigLine = 0;
+    for (String line = r.readLine(); line != null; line = r.readLine()) {
       lines.add(line);
-      if (line.indexOf('=')>0) {
+      if (line.indexOf('=') > 0) {
         lastConfigLine = lines.size();
       }
     }
     r.close();
     // copy props lines to string
     StringBuffer sb = new StringBuffer();
-    for (int i=0; i<lastConfigLine; i++) {
+    for (int i = 0; i < lastConfigLine; i++) {
       sb.append(lines.get(i));
       sb.append(NEW_LINE);
     }
@@ -80,17 +81,17 @@ public class Config {
     props.load(new ByteArrayInputStream(sb.toString().getBytes()));
 
     // make sure work dir is set properly 
-    if (props.get("work.dir")==null) {
-      props.setProperty("work.dir",System.getProperty("benchmark.work.dir","work"));
+    if (props.get("work.dir") == null) {
+      props.setProperty("work.dir", System.getProperty("benchmark.work.dir", "work"));
     }
-    
-    if (Boolean.valueOf(props.getProperty("print.props","true")).booleanValue()) {
+
+    if (Boolean.valueOf(props.getProperty("print.props", "true")).booleanValue()) {
       printProps();
     }
-    
+
     // copy algorithm lines
     sb = new StringBuffer();
-    for (int i=lastConfigLine; i<lines.size(); i++) {
+    for (int i = lastConfigLine; i < lines.size(); i++) {
       sb.append(lines.get(i));
       sb.append(NEW_LINE);
     }
@@ -121,147 +122,176 @@ public class Config {
 
   /**
    * Return a string property.
+   *
    * @param name name of property.
    * @param dflt default value.
    * @return a string property.
    */
-  public String get (String name, String dflt) {
-    return props.getProperty(name,dflt);
+  public String get(String name, String dflt) {
+    String vals[] = (String[]) valByRound.get(name);
+    if (vals != null) {
+      return vals[roundNumber % vals.length];
+    }
+    // done if not by round
+    String sval = props.getProperty(name, dflt);
+    if (sval == null) {
+      return null;
+    }
+    if (sval.indexOf(":") < 0) {
+      return sval;
+    }
+    // first time this prop is extracted by round
+    int k = sval.indexOf(":");
+    String colName = sval.substring(0, k);
+    sval = sval.substring(k + 1);
+    colForValByRound.put(name, colName);
+    vals = propToStringArray(sval);
+    valByRound.put(name, vals);
+    return vals[roundNumber % vals.length];
   }
 
   /**
    * Set a property.
    * Note: once a multiple values property is set, it can no longer be modified.
-   * @param name name of property.
+   *
+   * @param name  name of property.
    * @param value either single or multiple property value (multiple values are separated
by ":")
-   * @throws Exception 
+   * @throws Exception
    */
-  public void set (String name, String value) throws Exception {
+  public void set(String name, String value) throws Exception {
     if (valByRound.get(name) != null) {
       throw new Exception("Cannot modify a multi value property!");
     }
-    props.setProperty(name,value);
+    props.setProperty(name, value);
   }
 
   /**
    * Return an int property.
-   * If the property contain ":", e.g. "10:100:5", it is interpreted 
+   * If the property contain ":", e.g. "10:100:5", it is interpreted
    * as array of ints. It is extracted once, on first call
-   * to get() it, and a by-round-value is returned. 
+   * to get() it, and a by-round-value is returned.
+   *
    * @param name name of property
    * @param dflt default value
    * @return a int property.
    */
-  public int get (String name, int dflt) {
+  public int get(String name, int dflt) {
     // use value by round if already parsed
     int vals[] = (int[]) valByRound.get(name);
     if (vals != null) {
       return vals[roundNumber % vals.length];
     }
     // done if not by round 
-    String sval = props.getProperty(name,""+dflt);
-    if (sval.indexOf(":")<0) {
+    String sval = props.getProperty(name, "" + dflt);
+    if (sval.indexOf(":") < 0) {
       return Integer.parseInt(sval);
     }
     // first time this prop is extracted by round
     int k = sval.indexOf(":");
-    String colName = sval.substring(0,k);
-    sval = sval.substring(k+1);
-    colForValByRound.put(name,colName);
+    String colName = sval.substring(0, k);
+    sval = sval.substring(k + 1);
+    colForValByRound.put(name, colName);
     vals = propToIntArray(sval);
-    valByRound.put(name,vals);
+    valByRound.put(name, vals);
     return vals[roundNumber % vals.length];
   }
-  
+
   /**
    * Return a double property.
-   * If the property contain ":", e.g. "10:100:5", it is interpreted 
+   * If the property contain ":", e.g. "10:100:5", it is interpreted
    * as array of doubles. It is extracted once, on first call
-   * to get() it, and a by-round-value is returned. 
+   * to get() it, and a by-round-value is returned.
+   *
    * @param name name of property
    * @param dflt default value
    * @return a double property.
    */
-  public double get (String name, double dflt) {
+  public double get(String name, double dflt) {
     // use value by round if already parsed
     double vals[] = (double[]) valByRound.get(name);
     if (vals != null) {
       return vals[roundNumber % vals.length];
     }
     // done if not by round 
-    String sval = props.getProperty(name,""+dflt);
-    if (sval.indexOf(":")<0) {
+    String sval = props.getProperty(name, "" + dflt);
+    if (sval.indexOf(":") < 0) {
       return Double.parseDouble(sval);
     }
     // first time this prop is extracted by round
     int k = sval.indexOf(":");
-    String colName = sval.substring(0,k);
-    sval = sval.substring(k+1);
-    colForValByRound.put(name,colName);
+    String colName = sval.substring(0, k);
+    sval = sval.substring(k + 1);
+    colForValByRound.put(name, colName);
     vals = propToDoubleArray(sval);
-    valByRound.put(name,vals);
+    valByRound.put(name, vals);
     return vals[roundNumber % vals.length];
   }
-  
+
   /**
    * Return a boolean property.
-   * If the property contain ":", e.g. "true.true.false", it is interpreted 
+   * If the property contain ":", e.g. "true.true.false", it is interpreted
    * as array of booleans. It is extracted once, on first call
-   * to get() it, and a by-round-value is returned. 
+   * to get() it, and a by-round-value is returned.
+   *
    * @param name name of property
    * @param dflt default value
    * @return a int property.
    */
-  public boolean get (String name, boolean dflt) {
+  public boolean get(String name, boolean dflt) {
     // use value by round if already parsed
     boolean vals[] = (boolean[]) valByRound.get(name);
     if (vals != null) {
       return vals[roundNumber % vals.length];
     }
     // done if not by round 
-    String sval = props.getProperty(name,""+dflt);
-    if (sval.indexOf(":")<0) {
+    String sval = props.getProperty(name, "" + dflt);
+    if (sval.indexOf(":") < 0) {
       return Boolean.valueOf(sval).booleanValue();
     }
     // first time this prop is extracted by round 
     int k = sval.indexOf(":");
-    String colName = sval.substring(0,k);
-    sval = sval.substring(k+1);
-    colForValByRound.put(name,colName);
+    String colName = sval.substring(0, k);
+    sval = sval.substring(k + 1);
+    colForValByRound.put(name, colName);
     vals = propToBooleanArray(sval);
-    valByRound.put(name,vals);
+    valByRound.put(name, vals);
     return vals[roundNumber % vals.length];
   }
-  
+
   /**
-   * Increment the round number, for config values that are extracted by round number. 
+   * Increment the round number, for config values that are extracted by round number.
+   *
    * @return the new round number.
    */
-  public int newRound () {
+  public int newRound() {
     roundNumber++;
-    
-    StringBuffer sb = new StringBuffer("--> Round ").append(roundNumber-1).append("-->").append(roundNumber);
+
+    StringBuffer sb = new StringBuffer("--> Round ").append(roundNumber - 1).append("-->").append(roundNumber);
 
     // log changes in values
-    if (valByRound.size()>0) {
+    if (valByRound.size() > 0) {
       sb.append(": ");
       for (final String name : valByRound.keySet()) {
         Object a = valByRound.get(name);
         if (a instanceof int[]) {
           int ai[] = (int[]) a;
-          int n1 = (roundNumber-1)%ai.length;
-          int n2 = roundNumber%ai.length;
+          int n1 = (roundNumber - 1) % ai.length;
+          int n2 = roundNumber % ai.length;
           sb.append("  ").append(name).append(":").append(ai[n1]).append("-->").append(ai[n2]);
-        } else if (a instanceof double[]){
+        } else if (a instanceof double[]) {
           double ad[] = (double[]) a;
-          int n1 = (roundNumber-1)%ad.length;
-          int n2 = roundNumber%ad.length;
+          int n1 = (roundNumber - 1) % ad.length;
+          int n2 = roundNumber % ad.length;
           sb.append("  ").append(name).append(":").append(ad[n1]).append("-->").append(ad[n2]);
-        }
-        else {
+        } else if (a instanceof String[]) {
+          String ad[] = (String[]) a;
+          int n1 = (roundNumber - 1) % ad.length;
+          int n2 = roundNumber % ad.length;
+          sb.append("  ").append(name).append(":").append(ad[n1]).append("-->").append(ad[n2]);
+        } else {
           boolean ab[] = (boolean[]) a;
-          int n1 = (roundNumber-1)%ab.length;
-          int n2 = roundNumber%ab.length;
+          int n1 = (roundNumber - 1) % ab.length;
+          int n2 = roundNumber % ab.length;
           sb.append("  ").append(name).append(":").append(ab[n1]).append("-->").append(ab[n2]);
         }
       }
@@ -270,62 +300,76 @@ public class Config {
     System.out.println();
     System.out.println(sb.toString());
     System.out.println();
-    
+
     return roundNumber;
   }
-  
+
+  private String[] propToStringArray(String s) {
+    if (s.indexOf(":") < 0) {
+      return new String[]{s};
+    }
+
+    ArrayList<String> a = new ArrayList<String>();
+    StringTokenizer st = new StringTokenizer(s, ":");
+    while (st.hasMoreTokens()) {
+      String t = st.nextToken();
+      a.add(t);
+    }
+    return (String[]) a.toArray(new String[a.size()]);
+  }
+
   // extract properties to array, e.g. for "10:100:5" return int[]{10,100,5}. 
-  private int[] propToIntArray (String s) {
-    if (s.indexOf(":")<0) {
-      return new int [] { Integer.parseInt(s) };
+  private int[] propToIntArray(String s) {
+    if (s.indexOf(":") < 0) {
+      return new int[]{Integer.parseInt(s)};
     }
-    
+
     ArrayList<Integer> a = new ArrayList<Integer>();
-    StringTokenizer st = new StringTokenizer(s,":");
+    StringTokenizer st = new StringTokenizer(s, ":");
     while (st.hasMoreTokens()) {
       String t = st.nextToken();
       a.add(Integer.valueOf(t));
     }
-    int res[] = new int[a.size()]; 
-    for (int i=0; i<a.size(); i++) {
+    int res[] = new int[a.size()];
+    for (int i = 0; i < a.size(); i++) {
       res[i] = a.get(i).intValue();
     }
     return res;
   }
-    
+
   // extract properties to array, e.g. for "10.7:100.4:-2.3" return int[]{10.7,100.4,-2.3}.

-  private double[] propToDoubleArray (String s) {
-    if (s.indexOf(":")<0) {
-      return new double [] { Double.parseDouble(s) };
+  private double[] propToDoubleArray(String s) {
+    if (s.indexOf(":") < 0) {
+      return new double[]{Double.parseDouble(s)};
     }
-    
+
     ArrayList<Double> a = new ArrayList<Double>();
-    StringTokenizer st = new StringTokenizer(s,":");
+    StringTokenizer st = new StringTokenizer(s, ":");
     while (st.hasMoreTokens()) {
       String t = st.nextToken();
       a.add(Double.valueOf(t));
     }
-    double res[] = new double[a.size()]; 
-    for (int i=0; i<a.size(); i++) {
+    double res[] = new double[a.size()];
+    for (int i = 0; i < a.size(); i++) {
       res[i] = a.get(i).doubleValue();
     }
     return res;
   }
-    
+
   // extract properties to array, e.g. for "true:true:false" return boolean[]{true,false,false}.

-  private boolean[] propToBooleanArray (String s) {
-    if (s.indexOf(":")<0) {
-      return new boolean [] { Boolean.valueOf(s).booleanValue() };
+  private boolean[] propToBooleanArray(String s) {
+    if (s.indexOf(":") < 0) {
+      return new boolean[]{Boolean.valueOf(s).booleanValue()};
     }
-    
+
     ArrayList<Boolean> a = new ArrayList<Boolean>();
-    StringTokenizer st = new StringTokenizer(s,":");
+    StringTokenizer st = new StringTokenizer(s, ":");
     while (st.hasMoreTokens()) {
       String t = st.nextToken();
       a.add(new Boolean(t));
     }
-    boolean res[] = new boolean[a.size()]; 
-    for (int i=0; i<a.size(); i++) {
+    boolean res[] = new boolean[a.size()];
+    for (int i = 0; i < a.size(); i++) {
       res[i] = a.get(i).booleanValue();
     }
     return res;
@@ -335,10 +379,10 @@ public class Config {
    * @return names of params set by round, for reports title
    */
   public String getColsNamesForValsByRound() {
-    if (colForValByRound.size()==0) {
+    if (colForValByRound.size() == 0) {
       return "";
     }
-    StringBuffer sb = new StringBuffer(); 
+    StringBuffer sb = new StringBuffer();
     for (final String name : colForValByRound.keySet()) {
       String colName = colForValByRound.get(name);
       sb.append(" ").append(colName);
@@ -350,33 +394,35 @@ public class Config {
    * @return values of params set by round, for reports lines.
    */
   public String getColsValuesForValsByRound(int roundNum) {
-    if (colForValByRound.size()==0) {
+    if (colForValByRound.size() == 0) {
       return "";
     }
-    StringBuffer sb = new StringBuffer(); 
-    for (final String name  : colForValByRound.keySet()) {
+    StringBuffer sb = new StringBuffer();
+    for (final String name : colForValByRound.keySet()) {
       String colName = colForValByRound.get(name);
-      String template = " "+colName;
-      if (roundNum<0) {
+      String template = " " + colName;
+      if (roundNum < 0) {
         // just append blanks
-        sb.append(Format.formatPaddLeft("-",template));
+        sb.append(Format.formatPaddLeft("-", template));
       } else {
         // append actual values, for that round
         Object a = valByRound.get(name);
         if (a instanceof int[]) {
           int ai[] = (int[]) a;
           int n = roundNum % ai.length;
-          sb.append(Format.format(ai[n],template));
-        }
-        else if (a instanceof double[]) {
+          sb.append(Format.format(ai[n], template));
+        } else if (a instanceof double[]) {
           double ad[] = (double[]) a;
           int n = roundNum % ad.length;
-          sb.append(Format.format(2, ad[n],template));
-        }
-        else {
+          sb.append(Format.format(2, ad[n], template));
+        } else if (a instanceof String[]) {
+          String ad[] = (String[]) a;
+          int n = roundNum % ad.length;
+          sb.append(ad[n]);
+        } else {
           boolean ab[] = (boolean[]) a;
           int n = roundNum % ab.length;
-          sb.append(Format.formatPaddLeft(""+ab[n],template));
+          sb.append(Format.formatPaddLeft("" + ab[n], template));
         }
       }
     }



Mime
View raw message