[Swift-commit] r4835 - in trunk: libexec resources src/org/griphyn/vdl/engine src/org/griphyn/vdl/karajan src/org/griphyn/vdl/karajan/lib src/org/griphyn/vdl/karajan/lib/swiftscript src/org/griphyn/vdl/mapping src/org/griphyn/vdl/mapping/file src/org/griphyn/vdl/type src/org/griphyn/vdl/type/impl

hategan at ci.uchicago.edu hategan at ci.uchicago.edu
Sun Jul 24 18:04:12 CDT 2011


Author: hategan
Date: 2011-07-24 18:04:11 -0500 (Sun, 24 Jul 2011)
New Revision: 4835

Added:
   trunk/src/org/griphyn/vdl/karajan/lib/AppendArray.java
   trunk/src/org/griphyn/vdl/mapping/PathComparator.java
   trunk/src/org/griphyn/vdl/mapping/PathElementComparator.java
   trunk/src/org/griphyn/vdl/mapping/PathParser.java
   trunk/src/org/griphyn/vdl/mapping/PathParsingException.java
Modified:
   trunk/libexec/vdl-lib.xml
   trunk/resources/Karajan.stg
   trunk/resources/swiftscript.g
   trunk/resources/swiftscript.stg
   trunk/resources/swiftscript.xsd
   trunk/src/org/griphyn/vdl/engine/FormalArgumentSignature.java
   trunk/src/org/griphyn/vdl/engine/Karajan.java
   trunk/src/org/griphyn/vdl/karajan/ArrayIndexFutureList.java
   trunk/src/org/griphyn/vdl/karajan/lib/CleanDataset.java
   trunk/src/org/griphyn/vdl/karajan/lib/CreateArray.java
   trunk/src/org/griphyn/vdl/karajan/lib/DoRestartLog.java
   trunk/src/org/griphyn/vdl/karajan/lib/ExpandArguments.java
   trunk/src/org/griphyn/vdl/karajan/lib/GetArrayIterator.java
   trunk/src/org/griphyn/vdl/karajan/lib/GetField.java
   trunk/src/org/griphyn/vdl/karajan/lib/GetFieldSubscript.java
   trunk/src/org/griphyn/vdl/karajan/lib/IsDone.java
   trunk/src/org/griphyn/vdl/karajan/lib/New.java
   trunk/src/org/griphyn/vdl/karajan/lib/Operators.java
   trunk/src/org/griphyn/vdl/karajan/lib/Range.java
   trunk/src/org/griphyn/vdl/karajan/lib/SetFieldValue.java
   trunk/src/org/griphyn/vdl/karajan/lib/SliceArray.java
   trunk/src/org/griphyn/vdl/karajan/lib/SwiftArg.java
   trunk/src/org/griphyn/vdl/karajan/lib/VDLFunction.java
   trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Misc.java
   trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadData.java
   trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadStructured.java
   trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Sprintf.java
   trunk/src/org/griphyn/vdl/mapping/AbstractDataNode.java
   trunk/src/org/griphyn/vdl/mapping/ArrayDataNode.java
   trunk/src/org/griphyn/vdl/mapping/DSHandle.java
   trunk/src/org/griphyn/vdl/mapping/DataNode.java
   trunk/src/org/griphyn/vdl/mapping/InvalidPathException.java
   trunk/src/org/griphyn/vdl/mapping/Path.java
   trunk/src/org/griphyn/vdl/mapping/RootArrayDataNode.java
   trunk/src/org/griphyn/vdl/mapping/RootDataNode.java
   trunk/src/org/griphyn/vdl/mapping/file/AbstractFileMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/AirsnMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/ArrayFileMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/CSVMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/FileSystemArrayMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/FixedArrayFileMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/ROIMapper.java
   trunk/src/org/griphyn/vdl/mapping/file/StructuredRegularExpressionMapper.java
   trunk/src/org/griphyn/vdl/type/Field.java
   trunk/src/org/griphyn/vdl/type/Type.java
   trunk/src/org/griphyn/vdl/type/Types.java
   trunk/src/org/griphyn/vdl/type/impl/FieldImpl.java
   trunk/src/org/griphyn/vdl/type/impl/TypeImpl.java
   trunk/src/org/griphyn/vdl/type/impl/UnresolvedType.java
Log:
array key typing; array types declaration; internal storage of int changed to Integer

Modified: trunk/libexec/vdl-lib.xml
===================================================================
--- trunk/libexec/vdl-lib.xml	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/libexec/vdl-lib.xml	2011-07-24 23:04:11 UTC (rev 4835)
@@ -61,6 +61,7 @@
 	<export name="getField"><elementDef classname="org.griphyn.vdl.karajan.lib.GetField"/></export>
 	<export name="getFieldSubscript"><elementDef classname="org.griphyn.vdl.karajan.lib.GetFieldSubscript"/></export>
 	<export name="setFieldValue"><elementDef classname="org.griphyn.vdl.karajan.lib.SetFieldValue"/></export>
+	<export name="appendArray"><elementDef classname="org.griphyn.vdl.karajan.lib.AppendArray"/></export>
 	<export name="getFieldValue"><elementDef classname="org.griphyn.vdl.karajan.lib.GetFieldValue"/></export>
 	<export name="waitFieldValue"><elementDef classname="org.griphyn.vdl.karajan.lib.WaitFieldValue"/></export>
 	<export name="getArrayIterator"><elementDef classname="org.griphyn.vdl.karajan.lib.GetArrayIterator"/></export>

Modified: trunk/resources/Karajan.stg
===================================================================
--- trunk/resources/Karajan.stg	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/resources/Karajan.stg	2011-07-24 23:04:11 UTC (rev 4835)
@@ -198,7 +198,7 @@
 </vdl:infinitecountingwhile>
 >>
 
-foreach(var,in,indexVar,declarations,statements,line,selfClose,cleanups) ::= <<
+foreach(var,in,indexVar,indexVarType,declarations,statements,line,selfClose,cleanups) ::= <<
 <vdl:tparallelFor name="\$"$if(selfClose)$ selfClose="$selfClose$"$endif$>
   <getarrayiterator>$in$</getarrayiterator>
   <set names="\$\$, $var$">
@@ -206,7 +206,7 @@
   </set>
 $if(indexVar)$
     <set name="$indexVar$">
-      <vdl:new type="int" value="{\$\$}"/>
+      <vdl:new type="$indexVarType$" value="{\$\$}"/>
     </set>
 $endif$
 	<log level="debug" message="FOREACH_IT_START line=$line$ thread={#thread}"/>
@@ -343,15 +343,18 @@
 
 assign(var,value) ::= <<
    <vdl:setfieldvalue>
-     <argument name="var">
        $var$
-     </argument>
-     <argument name="value">
        $value$
-     </argument>
    </vdl:setfieldvalue>
 >>
 
+append(array, value) ::= <<
+	<vdl:appendArray>
+		$array$
+		$value$
+	</vdl:appendArray>
+>>
+
 callexpr(call, datatype, callID, prefix) ::= <<
 <sequential>
 	<set name="swift#callintermediate">

Modified: trunk/resources/swiftscript.g
===================================================================
--- trunk/resources/swiftscript.g	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/resources/swiftscript.g	2011-07-24 23:04:11 UTC (rev 4835)
@@ -166,6 +166,12 @@
         code.setAttribute("statements",d);
        }
 
+// these are non-declaration append-associative array statements
+ 
+	|   (predictAppendStat) => d=appendStat
+		{
+		 code.setAttribute("statements",d);
+		}
 
 // they all begin with (id name)
     | (predictDeclaration) => declaration[code]
@@ -206,10 +212,14 @@
         String thisType = (String) t.getAttribute("name");
         StringTemplate variable=null;
         StringTemplate m = null;
+        StringTemplate sTemp = null;
+		String sType = "";
     }
     :
      n=declarator
-     (LBRACK RBRACK {thisType = thisType + "[]"; } )*
+	(LBRACK
+	(sTemp=type {sType = (String) sTemp.getAttribute("name") ;} )? 
+	RBRACK {thisType = thisType + "[" + sType + "]" ; sType = ""; } )*
      {
         thisTypeTemplate=template("type");
         thisTypeTemplate.setAttribute("name", thisType);
@@ -465,14 +475,23 @@
         }
     ;
 
-type returns [StringTemplate code=null]
-    :
-     id:ID 
-        {
-        code=template("type");
-        code.setAttribute("name", id.getText());
-        }
-    ;
+type returns [ StringTemplate code = null ] 
+	{ StringBuilder buf = new StringBuilder(); }
+:
+	id:ID {
+		code = template("type");
+		buf.append(id.getText());
+	}
+	(typeSubscript[buf]) * {
+		code.setAttribute("name", buf.toString());
+	}
+;
+    
+typeSubscript[StringBuilder buf] :
+	LBRACK { buf.append('['); }
+	(id:ID { buf.append(id.getText()); })?
+	RBRACK { buf.append(']'); }
+;
 
 compoundStat[StringTemplate code]
     :   LCURLY
@@ -492,6 +511,7 @@
        s=ll1statement
     |  (procedurecallCode) => s=procedurecallCode
     |  (predictAssignStat) => s=assignStat
+    |  (predictAppendStat) => s=appendStat
     )
        {
         code.setAttribute("statements",s);
@@ -505,6 +525,7 @@
     (  code=ll1statement
     |  (procedurecallCode) => code=procedurecallCode
     |  (predictAssignStat) => code=assignStat
+    |  (predictAppendStat) => code=appendStat
     ) {statements.setAttribute("statements",code);}
     |   (procedurecallStatAssignManyReturnParam[statements]) => procedurecallStatAssignManyReturnParam[statements]
     ;
@@ -549,7 +570,7 @@
         code.setAttribute("var", id.getText());
         code.setAttribute("in", ds);
         if (indexId != null) {
-           code.setAttribute("index", indexId.getText());
+           code.setAttribute("index", indexId.getText());           
         }
     }
     compoundStat[body] {code.setAttribute("body", body);}
@@ -613,6 +634,10 @@
 {StringTemplate x=null;}
     : x=identifier ASSIGN ;
 
+predictAppendStat
+{StringTemplate x=null;}
+    : x=identifier APPEND ;    
+
 assignStat returns [StringTemplate code=null]
 {StringTemplate id=null;}
     :
@@ -632,6 +657,34 @@
     )
     ;
 
+appendStat returns [ StringTemplate code = null ]
+	{ StringTemplate id=null; }
+:
+    id=identifier
+    APPEND 
+    (
+    	(predictProcedurecallAssign) => code=procedurecallCode {
+    		StringTemplate o = template("returnParam");
+			o.setAttribute("name",id);
+			code.setAttribute("outputs",o);
+        }
+    	|
+      	code=arrayAppend { 
+			code.setAttribute("array", id);          
+		}
+    )
+;
+    
+arrayAppend returns [ StringTemplate code = null ]
+	{ StringTemplate a = null, e = null, id = null; }
+:
+	e = expression SEMI {
+		code = template("append");
+		code.setAttribute("value", e);
+	}
+;
+
+
 variableAssign returns [StringTemplate code=null]
 {StringTemplate a=null, e=null, id=null;}
     :
@@ -750,20 +803,27 @@
         }
     ;
 
-returnParameter returns [StringTemplate code=template("returnParam")]
-{StringTemplate t=null, id=null, d=null;}
-    :   (t=type{        code.setAttribute("type", t);})?
-        id=identifier
-        {
-        code.setAttribute("name", id);
-        }
-        (
-          (ASSIGN declarator)=>(ASSIGN d=declarator)
-          {
-          code.setAttribute("bind", d);
-          }
-        )?
-    ;
+returnParameter returns [ StringTemplate code = template("returnParam") ]
+	{ StringTemplate t = null, id = null, d = null; StringBuilder buf = new StringBuilder(); }
+:
+	t = identifier { buf.append(t.getAttribute("name")); }
+	(typeSubscript[buf])*
+	( id = identifier )?
+	{
+		if (id == null) {
+			code.setAttribute("name", t);
+		}
+		else {
+			t = template("type");
+			t.setAttribute("name", buf.toString());
+			code.setAttribute("name", id);
+			code.setAttribute("type", t);
+		}
+	}
+	((ASSIGN declarator) => (ASSIGN d=declarator) {
+		code.setAttribute("bind", d);
+	})?
+;
 
 actualParameter returns [StringTemplate code=template("actualParam")]
 {StringTemplate d=null, id=null, ai=null;}
@@ -1110,6 +1170,7 @@
 LE        :   "<=" ;
 GT        :   ">" ;
 GE        :   ">=";
+APPEND    :   "<<";
 ASSIGN  :   '=' ;
 AND        :   "&&";
 OR        :   "||";

Modified: trunk/resources/swiftscript.stg
===================================================================
--- trunk/resources/swiftscript.stg	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/resources/swiftscript.stg	2011-07-24 23:04:11 UTC (rev 4835)
@@ -266,6 +266,13 @@
 </assign>
 >>
 
+append(array,value,sourcelocation) ::= <<
+<append src="$sourcelocation$">
+ $array$
+ $value$
+</append>
+>>
+
 arraySubscript(array, subscript, sourcelocation) ::= <<
 <arraySubscript>
  $array$

Modified: trunk/resources/swiftscript.xsd
===================================================================
--- trunk/resources/swiftscript.xsd	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/resources/swiftscript.xsd	2011-07-24 23:04:11 UTC (rev 4835)
@@ -342,6 +342,17 @@
     <xs:attribute name="src" type="xs:string" />
 
   </xs:complexType>
+  
+  <xs:complexType name="Append">
+    <xs:annotation>
+      <xs:documentation>appends a value to an array
+      </xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element ref="abstractExpression" minOccurs="2" maxOccurs="2" />
+    </xs:sequence>
+    <xs:attribute name="src" type="xs:string" />
+  </xs:complexType>
 
   <xs:complexType name="Call">
     <xs:annotation>
@@ -393,6 +404,8 @@
       </xs:element>
 
       <xs:element name="assign" type="Assign"/>
+      
+      <xs:element name="append" type="Append"/>
 
       <xs:element name="call" type="Call"/>
 

Modified: trunk/src/org/griphyn/vdl/engine/FormalArgumentSignature.java
===================================================================
--- trunk/src/org/griphyn/vdl/engine/FormalArgumentSignature.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/engine/FormalArgumentSignature.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -1,5 +1,7 @@
 package org.griphyn.vdl.engine;
 
+import org.griphyn.vdl.type.Types;
+
 public class FormalArgumentSignature {
 	private String name;
 	private String type;
@@ -13,7 +15,7 @@
 	}
 	
 	public FormalArgumentSignature(String type, String name) {
-		this.type = type;
+		this.type = Types.normalize(type);
 		this.name = name;
 		this.anyType = false;
 		this.optionalArg = false;
@@ -25,7 +27,7 @@
 	}
 	
 	public FormalArgumentSignature(String type) {
-		this.type = type;
+		this.type = Types.normalize(type);
 		this.anyType = false;
 		this.optionalArg = false;
 	}

Modified: trunk/src/org/griphyn/vdl/engine/Karajan.java
===================================================================
--- trunk/src/org/griphyn/vdl/engine/Karajan.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/engine/Karajan.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -327,8 +327,9 @@
 				procST.setAttribute("optargs", paramST);
 			else
 				procST.setAttribute("arguments", paramST);
-			checkIsTypeDefined(param.getType().getLocalPart());
-			innerScope.addVariable(param.getName(), param.getType().getLocalPart());
+			String type = normalize(param.getType().getLocalPart());
+            checkIsTypeDefined(type);
+            innerScope.addVariable(param.getName(), type);
 		}
 		for (int i = 0; i < proc.sizeOfInputArray(); i++) {
 			FormalParameter param = proc.getInputArray(i);
@@ -338,8 +339,9 @@
 				procST.setAttribute("optargs", paramST);
 			else
 				procST.setAttribute("arguments", paramST);
-			checkIsTypeDefined(param.getType().getLocalPart());
-			outerScope.addVariable(param.getName(), param.getType().getLocalPart());
+			String type = normalize(param.getType().getLocalPart());
+			checkIsTypeDefined(type);
+			outerScope.addVariable(param.getName(), type);
 		}
 
 		Binding bind;
@@ -359,7 +361,7 @@
 		StringTemplate paramST = new StringTemplate("parameter");
 		StringTemplate typeST = new StringTemplate("type");
 		paramST.setAttribute("name", param.getName());
-		typeST.setAttribute("name", param.getType().getLocalPart());
+		typeST.setAttribute("name", normalize(param.getType().getLocalPart()));
 		typeST.setAttribute("namespace", param.getType().getNamespaceURI());
 		paramST.setAttribute("type", typeST);
 		if(!param.isNil())
@@ -463,15 +465,10 @@
 		scope.bodyTemplate.setAttribute("declarations", variableST);
 	}
 
-	void checkIsTypeDefined(String type) throws CompilationException {
-		while (type.length() > 2 && type.substring(type.length() - 2).equals("[]"))
-			type = type.substring(0, type.length() - 2);
-		if (!type.equals("int") && !type.equals("float") && !type.equals("string")
-				&& !type.equals("boolean") && !type.equals("external")) {
-			boolean typeDefined = typesMap.containsKey(type);
-			if (!typeDefined)
-				throw new CompilationException("Type " + type + " is not defined.");
-		}
+    void checkIsTypeDefined(String type) throws CompilationException {
+	    if (!org.griphyn.vdl.type.Types.isValidType(type, typesMap.keySet())) {
+	        throw new CompilationException("Type " + type + " is not defined.");
+	    }
 	}
 
 	public void assign(Assign assign, VariableScope scope) throws CompilationException {
@@ -492,6 +489,31 @@
 			throw new CompilationException("Compile error in assignment at "+assign.getSrc()+": "+re.getMessage(),re);
 		}
 	}
+	
+	public void append(Append append, VariableScope scope) throws CompilationException {
+        try {
+            StringTemplate appendST = template("append");
+            StringTemplate array = expressionToKarajan(append.getAbstractExpressionArray(0),scope);
+            StringTemplate value = expressionToKarajan(append.getAbstractExpressionArray(1),scope);
+            String indexType = org.griphyn.vdl.type.Types.getArrayIndexTypeName(datatype(array));
+            if (!"auto".equals(indexType)) {
+                throw new CompilationException("You can only append to an array with " +
+                		"'auto' index type. Current index type: " + indexType);
+            }
+            if (!datatype(value).equals(org.griphyn.vdl.type.Types.getArrayItemTypeName(datatype(array)))) {
+                throw new CompilationException("You cannot append value of type " + datatype(value) +
+                        " to an array of type " + datatype(array));
+            }
+            appendST.setAttribute("array", array);
+            appendST.setAttribute("value", value);
+            String rootvar = abstractExpressionToRootVariable(append.getAbstractExpressionArray(0));
+            // an append is always a partial write
+            scope.addWriter(rootvar, new Integer(callID++), true);
+            scope.appendStatement(appendST);
+        } catch(CompilationException re) {
+            throw new CompilationException("Compile error in assignment at "+append.getSrc()+": "+re.getMessage(),re);
+        }
+    }
 
 	public void statementsForSymbols(XmlObject prog, VariableScope scope) throws CompilationException {
 		XmlCursor cursor = prog.newCursor();
@@ -516,6 +538,7 @@
 			variableForSymbol((Variable) child, scope);
 		}
 		else if (child instanceof Assign
+		    || child instanceof Append
 			|| child instanceof Call
 			|| child instanceof Foreach
 			|| child instanceof Iterate
@@ -539,6 +562,9 @@
 		else if (child instanceof Assign) {
 			assign((Assign) child, scope);
 		}
+		else if (child instanceof Append) {
+		    append((Append) child, scope);
+		}
 		else if (child instanceof Call) {
 			call((Call) child, scope, false);
 		}
@@ -783,13 +809,16 @@
 			foreachST.setAttribute("in", inST);
 
 			String inType = datatype(inST);
-			if (inType.length() < 2 || !inType.substring(inType.length() - 2).equals("[]"))
-				throw new CompilationException("You can iterate through an array structure only");
-			String varType = inType.substring(0, inType.length() - 2);
-			innerScope.addVariable(foreach.getVar(), varType);
+			String itemType = org.griphyn.vdl.type.Types.getArrayItemTypeName(inType);
+			String keyType = org.griphyn.vdl.type.Types.getArrayIndexTypeName(inType);
+			if (itemType == null) {
+			    throw new CompilationException("You can iterate through an array structure only");
+			}
+			innerScope.addVariable(foreach.getVar(), itemType);
 			foreachST.setAttribute("indexVar", foreach.getIndexVar());
+			foreachST.setAttribute("indexVarType", keyType);
 			if(foreach.getIndexVar() != null) {
-				innerScope.addVariable(foreach.getIndexVar(), "int");
+				innerScope.addVariable(foreach.getIndexVar(), keyType);
 			}
 
 			innerScope.bodyTemplate = foreachST;
@@ -921,12 +950,19 @@
 				XmlObject argument = app.getAbstractExpressionArray(i);
 				StringTemplate argumentST = expressionToKarajan(argument, scope);
 				String type = datatype(argumentST);
-				if(type.equals("string") || type.equals("string[]")
-				 || type.equals("int") || type.equals("float")
-				 || type.equals("int[]") || type.equals("float[]")
-				 || type.equals("boolean") || type.equals("boolean[]")) {
-					appST.setAttribute("arguments", argumentST);
-				} else {
+				String base = org.griphyn.vdl.type.Types.getArrayItemTypeName(type);
+				String testType;
+				// if array then use the array item type for testing
+				if (base != null) {
+				    testType = base;
+				}
+				else {
+				    testType = type;
+				}
+				if (org.griphyn.vdl.type.Types.isPrimitive(testType)) {
+				    appST.setAttribute("arguments", argumentST);
+				} 
+				else {
 					throw new CompilationException("Cannot pass type '"+type+"' as a parameter to application '"+app.getExecutable()+"'");
 				}
 			}
@@ -1155,43 +1191,50 @@
 			StringTemplate arrayST = expressionToKarajan(op.getAbstractExpressionArray(1), scope);
 			StringTemplate parentST = expressionToKarajan(op.getAbstractExpressionArray(0), scope);
 
-			// handle [*] as identity/no-op
+			String indexType = datatype(arrayST);
+			String declaredIndexType = org.griphyn.vdl.type.Types.getArrayIndexTypeName(datatype(parentST));
+			// the index type must match the declared index type,
+			// unless the declared index type is *
+			
+			// and really, at this point type checking should be delegated to the type system
+			// instead of the ad-hoc string comparisons
 			if (datatype(arrayST).equals("string")) {
-				XmlString var = (XmlString) op.getAbstractExpressionArray(1);
-				if (var.getStringValue().equals("*")) {
-					return parentST;
-				} else {
-				   throw new CompilationException("Array index must be of type int, or *.");
-				}
-			} else {
-				// the index should be numerical
+                XmlString var = (XmlString) op.getAbstractExpressionArray(1);
+                if (var.getStringValue().equals("*")) {
+                    return parentST;
+                }
+            }
+			
+			if (!indexType.equals(declaredIndexType) 
+			        && !"".equals(declaredIndexType) 
+			        && !"any".equals(declaredIndexType)) {
+			    throw new CompilationException("Supplied array index type (" 
+			        + indexType + ") does not match the declared index type (" + declaredIndexType + ")");
+			}
+			
+			StringTemplate newst = template("extractarrayelement");
+			newst.setAttribute("arraychild", arrayST);
+			newst.setAttribute("parent", parentST);
+			newst.setAttribute("datatype", org.griphyn.vdl.type.Types.getArrayItemTypeName(datatype(parentST)));
 
-				StringTemplate newst = template("extractarrayelement");
-				newst.setAttribute("arraychild", arrayST);
-				newst.setAttribute("parent", parentST);
-
-				String arrayType = datatype(parentST);
-				if (datatype(arrayST).equals("int")) {
-					newst.setAttribute("datatype", arrayType.substring(0, arrayType.length()-2));
-				} else {
-					throw new CompilationException("Array index must be of type int, or *.");
-				}
-				return newst;
-			}
+			return newst;
 		} else if (expressionQName.equals(STRUCTURE_MEMBER_EXPR)) {
 			StructureMember sm = (StructureMember) expression;
 			StringTemplate parentST = expressionToKarajan(sm.getAbstractExpression(), scope);
 
 			String parentType = datatype(parentST);
 
-
 			// if the parent is an array, then check against
 			// the base type of the array
+			
+			String baseType = org.griphyn.vdl.type.Types.getArrayItemTypeName(parentType);
+			String indexType = org.griphyn.vdl.type.Types.getArrayIndexTypeName(parentType);
+			String arrayType = parentType;
 
 			boolean arrayMode = false;
-			if(parentType.endsWith("[]")) {
-				arrayMode=true;
-				parentType = parentType.substring(0, parentType.length() - 2);
+			if (baseType != null) {
+				arrayMode = true;
+				parentType = baseType;
 			}
 
 			String actualType = null;
@@ -1212,20 +1255,18 @@
 			if (actualType == null) {
 				throw new CompilationException("Type " + parentType + " is not defined.");
 			}
+			StringTemplate newst;
 			if(arrayMode) {
-				actualType += "[]";
-				StringTemplate newst = template("slicearray");
-				newst.setAttribute("parent", parentST);
-				newst.setAttribute("memberchild", sm.getMemberName());
-				newst.setAttribute("datatype", actualType);
-				return newst;
-			} else {
-				StringTemplate newst = template("extractstructelement");
-				newst.setAttribute("parent", parentST);
-				newst.setAttribute("memberchild", sm.getMemberName());
-				newst.setAttribute("datatype", actualType);
-				return newst;
+			    actualType = actualType + "[" + indexType + "]";
+				newst = template("slicearray");
+			} 
+			else {
+				newst = template("extractstructelement");
 			}
+			newst.setAttribute("parent", parentST);
+			newst.setAttribute("memberchild", sm.getMemberName());
+            newst.setAttribute("datatype", actualType);
+            return newst;
 			// TODO the template layout for this and ARRAY_SUBSCRIPT are
 			// both a bit convoluted for historical reasons.
 			// should be straightforward to tidy up.
@@ -1244,7 +1285,7 @@
 			}
 			if (elemType.equals(""))
 				logger.warn("WARNING: Empty array constant");
-			st.setAttribute("datatype", elemType + "[]");
+			st.setAttribute("datatype", elemType + "[int]");
 			return st;
 		} else if (expressionQName.equals(RANGE_EXPR)) {
 			Range range = (Range)expression;
@@ -1261,16 +1302,20 @@
 
 			String fromType = datatype(fromST);
 			String toType = datatype(toST);
-			if (stepST == null && (!fromType.equals("int") || !toType.equals("int")))
+			if (stepST == null && (!fromType.equals("int") || !toType.equals("int"))) {
 				throw new CompilationException("Step in range specification can be omitted only when from and to types are int");
+			}
 			else if ((fromType.equals("int") && toType.equals("int")) &&
-					(stepST == null || datatype(stepST).equals("int")))
-				st.setAttribute("datatype", "int[]");
+					(stepST == null || datatype(stepST).equals("int"))) {
+				st.setAttribute("datatype", "int[int]");
+			}
 			else if (fromType.equals("float") && toType.equals("float") &&
-					datatype(stepST).equals("float"))
-				st.setAttribute("datatype", "float[]");
-			else
+					datatype(stepST).equals("float")) {
+				st.setAttribute("datatype", "float[int]");
+			}
+			else {
 				throw new CompilationException("Range can only be specified with numeric types");
+			}
 			return st;
 		} else if (expressionQName.equals(FUNCTION_EXPR)) {
 			Function f = (Function) expression;
@@ -1430,15 +1475,17 @@
 	String escapeQuotes(String in) {
 		return in.replaceAll("\"", """);
 	}
+	
+	public static String normalize(String type) {
+	    return org.griphyn.vdl.type.Types.normalize(type);
+	}
 
 	String datatype(StringTemplate st) {
-	    String result = null;
 	    try {
-	        result = st.getAttribute("datatype").toString();
+	        return normalize(st.getAttribute("datatype").toString());
 	    }
 	    catch (Exception e) {
 	        throw new RuntimeException("Not typed properly: " + st);
 	    }
-	    return result;
 	}
 }

Modified: trunk/src/org/griphyn/vdl/karajan/ArrayIndexFutureList.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/ArrayIndexFutureList.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/ArrayIndexFutureList.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -30,6 +30,7 @@
         this.node = node;
         this.values = values;
         keys = new ArrayList<Object>();
+        keys.addAll(values.keySet());
     }
 
     public Object get(int index) {

Added: trunk/src/org/griphyn/vdl/karajan/lib/AppendArray.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/AppendArray.java	                        (rev 0)
+++ trunk/src/org/griphyn/vdl/karajan/lib/AppendArray.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Jul 21, 2011
+ */
+package org.griphyn.vdl.karajan.lib;
+
+import org.globus.cog.karajan.arguments.Arg;
+import org.globus.cog.karajan.stack.VariableStack;
+import org.globus.cog.karajan.util.TypeUtil;
+import org.globus.cog.karajan.workflow.ExecutionException;
+import org.griphyn.vdl.mapping.AbstractDataNode;
+import org.griphyn.vdl.mapping.DSHandle;
+import org.griphyn.vdl.mapping.InvalidPathException;
+import org.griphyn.vdl.mapping.Path;
+
+public class AppendArray extends SetFieldValue {
+    
+    public static final Arg PA_ID = new Arg.Positional("id");
+
+    static {
+        setArguments(AppendArray.class, new Arg[] { PA_VAR, PA_VALUE });
+    }
+    
+    @Override
+    public Object function(VariableStack stack) throws ExecutionException {
+        DSHandle var = (DSHandle) PA_VAR.getValue(stack);
+        AbstractDataNode value = (AbstractDataNode) PA_VALUE.getValue(stack);
+        // while there isn't a way to avoid conflicts between auto generated indices
+        // and a user manually using the same index, adding a "#" may reduce
+        // the incidence of problems
+        Path path = Path.EMPTY_PATH.addFirst(getThreadPrefix(stack), true);
+        try {
+            deepCopy(var.getField(path), value, stack, 0);
+        }
+        catch (InvalidPathException e) {
+            throw new ExecutionException(e);
+        }
+        return null;
+    }
+}

Modified: trunk/src/org/griphyn/vdl/karajan/lib/CleanDataset.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/CleanDataset.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/CleanDataset.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -32,7 +32,9 @@
 	    }
 	    else {
     		AbstractDataNode var = (AbstractDataNode) PA_VAR.getValue(stack);
-    		logger.info("Cleaning " + var);
+    		if (logger.isInfoEnabled()) {
+    		    logger.info("Cleaning " + var);
+    		}
     		var.clean();
 	    }
 	    return null;

Modified: trunk/src/org/griphyn/vdl/karajan/lib/CreateArray.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/CreateArray.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/CreateArray.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -69,7 +69,7 @@
 				DSHandle n = (DSHandle) i.next();
 				// we know this DSHandle cast will work because we checked
 				// it in the previous scan of the array contents
-				Path p = Path.EMPTY_PATH.addLast(String.valueOf(index), true);
+				Path p = Path.EMPTY_PATH.addLast(index, true);
 
 				handle.getField(p).set(n);
 				logger.info("CREATEARRAY MEMBER array="+handle.getIdentifier()+" index="+index+" member="+n.getIdentifier());

Modified: trunk/src/org/griphyn/vdl/karajan/lib/DoRestartLog.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/DoRestartLog.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/DoRestartLog.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -29,7 +29,7 @@
         try {
             for (Object f : files) {
                 List pv = TypeUtil.toList(f);
-                Path p = Path.parse(TypeUtil.toString(pv.get(0)));
+                Path p = (Path) pv.get(0);
                 DSHandle handle = (DSHandle) pv.get(1);
                 LogVar.logVar(stack, handle, p);
             }

Modified: trunk/src/org/griphyn/vdl/karajan/lib/ExpandArguments.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/ExpandArguments.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/ExpandArguments.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -1,19 +1,19 @@
 package org.griphyn.vdl.karajan.lib;
 
 import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
 import java.util.Map;
-import java.util.Comparator;
+import java.util.Set;
 import java.util.TreeSet;
-import java.util.Set;
-import java.util.Iterator;
 
 import org.apache.log4j.Logger;
 import org.globus.cog.karajan.arguments.Arg;
 import org.globus.cog.karajan.stack.VariableStack;
 import org.globus.cog.karajan.workflow.ExecutionException;
-
 import org.griphyn.vdl.mapping.ArrayDataNode;
 import org.griphyn.vdl.mapping.DSHandle;
+import org.griphyn.vdl.mapping.PathElementComparator;
 
 public class ExpandArguments extends VDLFunction {
 	public static final Logger logger = Logger.getLogger(ExpandArguments.class);
@@ -35,7 +35,7 @@
 				ArrayDataNode array = (ArrayDataNode) item;
 				Map m=array.getArrayValue();
 				Set keySet = m.keySet();
-				TreeSet sortedKeySet = new TreeSet(new StringsAsIntegersComparator());
+				TreeSet<Comparable<?>> sortedKeySet = new TreeSet<Comparable<?>>(new PathElementComparator());
 				sortedKeySet.addAll(keySet);
 				Iterator it = sortedKeySet.iterator();
 				while(it.hasNext()) {

Modified: trunk/src/org/griphyn/vdl/karajan/lib/GetArrayIterator.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/GetArrayIterator.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/GetArrayIterator.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -38,9 +38,15 @@
 				}
 				synchronized(var) {
 					if (var.isClosed()) {
+					    if (logger.isDebugEnabled()) {
+					        logger.debug("Using closed iterator for " + var);
+					    }
 						return new PairIterator(var.getArrayValue());
 					}
 					else {
+					    if (logger.isDebugEnabled()) {
+                            logger.debug("Using future iterator for " + var);
+                        }
 						return ((ArrayDataNode) var).getFutureList().futureIterator();
 					}
 				}

Modified: trunk/src/org/griphyn/vdl/karajan/lib/GetField.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/GetField.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/GetField.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -21,7 +21,6 @@
 	public Object function(VariableStack stack) throws ExecutionException {
 		Object var1 = PA_VAR.getValue(stack);
 
-
 		if(var1 instanceof DSHandle) {
 
 			try {

Modified: trunk/src/org/griphyn/vdl/karajan/lib/GetFieldSubscript.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/GetFieldSubscript.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/GetFieldSubscript.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -29,14 +29,11 @@
 
 		try {
 			Path path;
-			if (index instanceof String) {
-				path = Path.EMPTY_PATH.addFirst((String) index, true);
+			if ("*".equals(index)) {
+			    path = Path.CHILDREN;
 			}
-			else if (index instanceof Double) {
-				path = Path.EMPTY_PATH.addFirst(String.valueOf(((Double) index).intValue()), true);
-			}
 			else {
-				throw new RuntimeException("Cannot handle array index of Java type " + index.getClass());
+				path = Path.EMPTY_PATH.addFirst((Comparable<?>) index, true);
 			}
 			Collection<DSHandle> fields = var.getFields(path);
 			if (fields.size() == 1) {

Modified: trunk/src/org/griphyn/vdl/karajan/lib/IsDone.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/IsDone.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/IsDone.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -23,9 +23,9 @@
     @Override
     protected Object function(VariableStack stack) throws ExecutionException {
         List files = TypeUtil.toList(STAGEOUT.getValue(stack));
-        for (Object f : files) { 
+        for (Object f : files) {
             List pv = TypeUtil.toList(f);
-            Path p = Path.parse(TypeUtil.toString(pv.get(0)));
+            Path p = (Path) pv.get(0);
             DSHandle handle = (DSHandle) pv.get(1);
             if (!IsLogged.isLogged(stack, handle, p)) {
                 return Boolean.FALSE;

Modified: trunk/src/org/griphyn/vdl/karajan/lib/New.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/New.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/New.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -103,7 +103,7 @@
 							// TODO check type consistency of elements with
 							// the type of the array
 							Object n = i.next();
-							Path p = Path.EMPTY_PATH.addLast(String.valueOf(index), true);
+							Path p = Path.EMPTY_PATH.addLast(index, true);
 							if (n instanceof DSHandle) {
 								handle.getField(p).set((DSHandle) n);
 							}

Modified: trunk/src/org/griphyn/vdl/karajan/lib/Operators.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/Operators.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/Operators.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -24,7 +24,12 @@
 	private DSHandle newNum(Type type, double value) throws ExecutionException {
 		try {
 			DSHandle handle = new RootDataNode(type);
-			handle.setValue(new Double(value));
+			if (type == Types.INT) {
+			    handle.setValue(Integer.valueOf((int) value));
+			}
+			else {
+			    handle.setValue(new Double(value));
+			}
 			handle.closeShallow();
 			return handle;
 		}
@@ -33,6 +38,18 @@
 		}
 	}
 	
+	private DSHandle newNum(Type type, int value) throws ExecutionException {
+        try {
+            DSHandle handle = new RootDataNode(type);
+            handle.setValue(new Integer(value));
+            handle.closeShallow();
+            return handle;
+        }
+        catch (Exception e) {
+            throw new ExecutionException("Internal error", e);
+        }
+    }
+	
 	private DSHandle newString(String value) throws ExecutionException {
 		try {
 			DSHandle handle = new RootDataNode(Types.STRING);
@@ -86,12 +103,16 @@
 	public Object vdlop_sum(VariableStack stack) throws ExecutionException {
 		Object l = L.getValue(stack);
 		Object r = R.getValue(stack);
+		Type t = type(stack);
 		DSHandle ret;
 		if (l instanceof String || r instanceof String) {
 			ret = newString(((String) l) + ((String) r));
 		}
+		else if (t == Types.INT) {
+		    ret = newNum(t, SwiftArg.checkInt(l) + SwiftArg.checkInt(r));
+		}
 		else {
-			ret = newNum(type(stack), SwiftArg.checkDouble(l) + SwiftArg.checkDouble(r));
+			ret = newNum(t, SwiftArg.checkDouble(l) + SwiftArg.checkDouble(r));
 		}
 		logBinaryProvenance(stack, "sum", ret);
 		return ret;

Modified: trunk/src/org/griphyn/vdl/karajan/lib/Range.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/Range.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/Range.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -60,7 +60,7 @@
 						return Collections.singletonList((DSHandle) this);
 					}
 					else {
-						int index = Integer.parseInt(path.getFirst());
+						int index = (Integer) path.getFirst();
 						DSHandle value = new RootDataNode(type);
 						value.init(null);
 						value.setValue(new Double(start + incr * index));
@@ -91,13 +91,18 @@
 													{
 														value = new RootDataNode(type);
 														value.init(null);
-														value.setValue(new Double(crt));
+														if (type == Types.INT) {
+														    value.setValue(new Integer((int) crt));
+														}
+														else {
+														    value.setValue(new Double(crt));
+														}
 														value.closeShallow();
 														key = index;
 													}
 
 													public Comparable<?> getKey() {
-														return new Double(key);
+														return Integer.valueOf(key);
 													}
 
 													public DSHandle getValue() {

Modified: trunk/src/org/griphyn/vdl/karajan/lib/SetFieldValue.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/SetFieldValue.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/SetFieldValue.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -68,23 +68,24 @@
 	            if (p.equals("$"))
 	                p = "";
 	            String name = data.getDisplayableName() + p;
-	            Object v = value.getValue();
-	            if (! (v instanceof Map))
-	                logger.info("Set: " + name + "=" + v);
-	            else
+	            if (value.getType().isArray()) {
 	                logger.info("Set: " + name + "=" + 
-	                            unpackHandles((Map<String, DSHandle>) v));
+                                unpackHandles(value.getArrayValue()));
+	            }
+	            else {
+	                logger.info("Set: " + name + "=" + value.getValue());
+	            }
 	        }
 	    }
     }
 
-	String unpackHandles(Map<String,DSHandle> handles) { 
+	String unpackHandles(Map<Comparable<?>, DSHandle> handles) { 
 	    StringBuilder sb = new StringBuilder();
 	    sb.append("{");
-	    Iterator<Map.Entry<String,DSHandle>> it = 
+	    Iterator<Map.Entry<Comparable<?>, DSHandle>> it = 
 	        handles.entrySet().iterator();
 	    while (it.hasNext()) { 
-	        Map.Entry<String,DSHandle> entry = it.next();
+	        Map.Entry<Comparable<?>, DSHandle> entry = it.next();
 	        sb.append(entry.getKey());
 	        sb.append('=');
 	        sb.append(entry.getValue().getValue());
@@ -113,21 +114,15 @@
 			}
 			while (it.hasNext()) {
 				Pair pair = (Pair) it.next();
-				Object lhs = pair.get(0);
+				Comparable<?> lhs = (Comparable<?>) pair.get(0);
 				DSHandle rhs = (DSHandle) pair.get(1);
-				Path memberPath;
-				if (lhs instanceof Double) {
-				    memberPath = Path.EMPTY_PATH.addLast(String.valueOf(((Double) lhs).intValue()), true);
-				}
-				else {
-				    memberPath = Path.EMPTY_PATH.addLast(String.valueOf(lhs), true);
-				}
+				Path memberPath = Path.EMPTY_PATH.addLast(lhs, true);
 				DSHandle field;
 				try {
 					field = dest.getField(memberPath);
 				}
 				catch (InvalidPathException ipe) {
-					throw new ExecutionException("Could not get destination field",ipe);
+					throw new ExecutionException("Could not get destination field", ipe);
 				}
 				deepCopy(field, rhs, stack, level + 1);
 			}

Modified: trunk/src/org/griphyn/vdl/karajan/lib/SliceArray.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/SliceArray.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/SliceArray.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -60,21 +60,20 @@
 				RootArrayDataNode destinationArray = new RootArrayDataNode(destinationType);
 
 
-                               	Path cutPath = Path.EMPTY_PATH.addLast((String)PA_PATH.getValue(stack), false);
+				Path cutPath = Path.EMPTY_PATH.addLast((String) PA_PATH.getValue(stack), false);
 
-                        	PairIterator it = new PairIterator(sourceArray.getArrayValue());
+				PairIterator it = new PairIterator(sourceArray.getArrayValue());
 
 				while(it.hasNext()) {
 					Pair pair = (Pair) it.next();
 					Object index = pair.get(0);
 					DSHandle sourceElement = (DSHandle) pair.get(1);
 
+					Path p = Path.EMPTY_PATH.addLast((Comparable<?>) index, true);
 
-                                	Path p = Path.EMPTY_PATH.addLast(String.valueOf(index), true);
-
 					DSHandle n = sourceElement.getField(cutPath);
 
-                                	destinationArray.getField(p).set((DSHandle) n);
+					destinationArray.getField(p).set(n);
 				}
 
 				// all of the inputs should be closed, so

Modified: trunk/src/org/griphyn/vdl/karajan/lib/SwiftArg.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/SwiftArg.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/SwiftArg.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -66,13 +66,22 @@
 	}
 	
 	public static double checkDouble(Object dbl) throws ExecutionException {
-		if (dbl instanceof Double) {
-			return ((Double) dbl).doubleValue();
+		if (dbl instanceof Number) {
+			return ((Number) dbl).doubleValue();
 		}
 		else {
 			throw new ExecutionException("Internal type error. Expected a Double. Got " + classOf(dbl));
 		}
 	}
+	
+	public static int checkInt(Object i) throws ExecutionException {
+        if (i instanceof Integer) {
+            return ((Integer) i).intValue();
+        }
+        else {
+            throw new ExecutionException("Internal type error. Expected a Integer. Got " + classOf(i));
+        }
+    }
 
 	public DSHandle getRawValue(VariableStack stack) throws ExecutionException {
 		Object v = super.getValue(stack);

Modified: trunk/src/org/griphyn/vdl/karajan/lib/VDLFunction.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/VDLFunction.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/VDLFunction.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -3,7 +3,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -41,6 +40,7 @@
 import org.griphyn.vdl.mapping.InvalidPathException;
 import org.griphyn.vdl.mapping.Mapper;
 import org.griphyn.vdl.mapping.Path;
+import org.griphyn.vdl.mapping.PathComparator;
 import org.griphyn.vdl.mapping.PhysicalFormat;
 import org.griphyn.vdl.type.Type;
 import org.griphyn.vdl.type.Types;
@@ -154,7 +154,7 @@
 			return new Double(TypeUtil.toDouble(value));
 		}
 		else if (Types.INT.equals(type)) {
-			return new Double(TypeUtil.toInt(value));
+			return new Integer(TypeUtil.toInt(value));
 		}
 		else if (Types.BOOLEAN.equals(type)) {
 			return new Boolean(TypeUtil.toBoolean(value));
@@ -222,50 +222,6 @@
 		return l.toArray(EMPTY_STRING_ARRAY);
 	}
 	
-	private static class PathComparator implements Comparator<Path> {
-		public int compare(Path p1, Path p2) {
-			for (int i = 0; i < Math.min(p1.size(), p2.size()); i++) {
-				int d; 
-				d = indexOrder(p1.isArrayIndex(i), p2.isArrayIndex(i));
-				if (d != 0) {
-					return d;
-				}
-				if (p1.isArrayIndex(i)) {
-					d = numericOrder(p1.getElement(i), p2.getElement(i));
-				}
-				else {
-					d = p1.getElement(i).compareTo(p2.getElement(i));
-				}
-				if (d != 0) {
-					return d;
-				}
-			}
-			//the longer one wins
-			return p1.size() - p2.size();
-		}
-		
-		private int indexOrder(boolean i1, boolean i2) {
-			//it doesn't matter much what the order between indices and non-indices is,
-			//but it needs to be consistent
-			if (i1) {
-				if (!i2) {
-					return -1;
-				}
-			}
-			else {
-				if (i2) {
-					return 1;
-				}
-			}
-			return 0;
-		}
-		
-		private int numericOrder(String i1, String i2) {
-			//TODO check if we're actually dealing with numeric indices
-			return Integer.parseInt(i1) - Integer.parseInt(i2);
-		}
-	}
-	
 	private static String leafFileName(DSHandle var) throws ExecutionException {
 	    return leafFileName(var, var.getMapper());
 	}
@@ -408,43 +364,12 @@
 	}
 
 	public static Path parsePath(Object o, VariableStack stack) throws ExecutionException {
-		Path q = Path.EMPTY_PATH;
-		Path p;
 		if (o instanceof Path) {
-			p = (Path) o;
+			return (Path) o;
 		}
 		else {
-			p = Path.parse(TypeUtil.toString(o));
+			return Path.parse(TypeUtil.toString(o));
 		}
-		for (int i = 0; i < p.size(); i++) {
-			if (p.isArrayIndex(i)) {
-				if (p.isWildcard(i)) {
-					q = q.addLast(p.getElement(i), true);
-				}
-				else {
-					String index = p.getElement(i);
-					try {
-						// check this is can parse as an integer by trying to parse and getting an exception if not
-						Integer.parseInt(index);
-						q = q.addLast(index, true);
-					}
-					catch (NumberFormatException e) {
-						Object v = stack.getVar(index);
-						if (v instanceof DSHandle) {
-							v = ((DSHandle) v).getValue();
-						}
-						q = q.addLast(TypeUtil.toString(v), true);
-					}
-				}
-			}
-			else {
-				q = q.addLast(p.getElement(i));
-			}
-		}
-		if (p.hasWildcards() && !q.hasWildcards()) {
-			throw new RuntimeException("Error in the wildcard processing routine");
-		}
-		return q;
 	}
 
 	private static Set warnset = new HashSet();

Modified: trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Misc.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Misc.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Misc.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -87,6 +87,22 @@
     	            buf.append(o);
     	        }
     	    }
+    	    else if (h.getType().isArray()) {
+    	        buf.append('{');
+    	        boolean first = true;
+    	        for (Map.Entry<Comparable<?>, DSHandle> e : h.getArrayValue().entrySet()) {
+    	            if (first) {
+    	                first = false;
+    	            }
+    	            else {
+    	                buf.append(", ");
+    	            }
+    	            buf.append(e.getKey());
+    	            buf.append(" = ");
+    	            prettyPrint(buf, e.getValue());
+    	        }
+    	        buf.append('}');
+    	    }
     	    else {
     	        buf.append(h);
     	    }
@@ -105,8 +121,7 @@
 			buf.append(TypeUtil.toString(args[i]));
 		}
 		
-		DSHandle handle = new RootDataNode(Types.STRING);
-		handle.setValue(buf.toString());
+		DSHandle handle = new RootDataNode(Types.STRING, buf.toString());
 
 		try {
 			if(VDL2Config.getConfig().getProvenanceLog()) {
@@ -134,11 +149,9 @@
 
 		String filename = TypeUtil.toString(args[0]);
 
-		DSHandle handle = new RootDataNode(Types.BOOLEAN);
 		AbsFile file = new AbsFile(filename);
 		logger.debug("exists: " + file);
-		handle.setValue(file.exists());
-		handle.closeShallow();
+		DSHandle handle = new RootDataNode(Types.BOOLEAN, file.exists());
 
 		try {
 			if(VDL2Config.getConfig().getProvenanceLog()) {
@@ -185,9 +198,8 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug("strcut matched '" + group + "'");
 		}
-		DSHandle handle = new RootDataNode(Types.STRING);
-		handle.setValue(group);
-		handle.closeShallow();
+		DSHandle handle = new RootDataNode(Types.STRING, group);
+
 		VDLFunction.logProvenanceResult(provid, handle, "strcut");
 		VDLFunction.logProvenanceParameter(provid, PA_INPUT.getRawValue(stack), "input");
 		VDLFunction.logProvenanceParameter(provid, PA_PATTERN.getRawValue(stack), "pattern");
@@ -203,10 +215,7 @@
                 "' for pattern '" + pattern + "'");
         }
         int result = inputString.indexOf(pattern);
-        DSHandle handle = new RootDataNode(Types.INT);
-        handle.setValue(new Double(result));
-        handle.closeShallow();
-        return handle;
+        return new RootDataNode(Types.INT, result);
     }
 
 	public DSHandle swiftscript_strsplit(VariableStack stack)
@@ -219,7 +228,7 @@
 
 		DSHandle handle = new RootArrayDataNode(Types.STRING.arrayType());
 		for (int i = 0; i < split.length; i++) {
-			DSHandle el = handle.getField(Path.EMPTY_PATH.addFirst(String.valueOf(i), true));
+			DSHandle el = handle.getField(Path.EMPTY_PATH.addFirst(i, true));
 			el.setValue(split[i]);
 		}
 		handle.closeDeep();
@@ -279,7 +288,7 @@
 
 		try
 		{
-		    handle.setValue(new Double(inputString));
+		    handle.setValue(new Integer(inputString));
 		}
 		catch(NumberFormatException e)
 		{
@@ -403,12 +412,7 @@
 	    Object[] args = SwiftArg.VARGS.asArray(stack);
 	    String arg = (String) args[0];
 	    AbsFile file = new AbsFile(arg);
-	    boolean b = file.exists();
-	    result = new RootDataNode(Types.BOOLEAN);
-	    result.setValue(b);
-	    result.closeShallow();
-
-        return result;
+	    return new RootDataNode(Types.BOOLEAN, file.exists());
 	}
 }
 

Modified: trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadData.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadData.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadData.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -119,7 +119,7 @@
 		String line = br.readLine();
 		try {
 			while (line != null) {
-				DSHandle child = dest.getField(Path.EMPTY_PATH.addLast(String.valueOf(index), true));
+				DSHandle child = dest.getField(Path.EMPTY_PATH.addLast(index, true));
 				setValue(child, line);
 				line = br.readLine();
 				index++;
@@ -139,8 +139,7 @@
 			while (line != null) {
 				line = line.trim();
 				if (!line.equals("")) {
-					DSHandle child = dest.getField(Path.EMPTY_PATH.addLast(String.valueOf(index),
-							true));
+					DSHandle child = dest.getField(Path.EMPTY_PATH.addLast(index, true));
 					readStruct(child, line, header);
 					index++;
 				}
@@ -211,13 +210,13 @@
 		try {
 
 			if (dest.getType().equals(Types.INT)) {
-				dest.setValue(new Double(Integer.parseInt(s.trim())));
+				dest.setValue(Integer.valueOf(s.trim()));
 			}
 			else if (dest.getType().equals(Types.FLOAT)) {
 				dest.setValue(new Double(s.trim()));
 			}
 			else if (dest.getType().equals(Types.BOOLEAN)) {
-				dest.setValue(new Boolean(s.trim()));
+				dest.setValue(Boolean.valueOf(s.trim()));
 			}
 			else if (dest.getType().equals(Types.STRING)) {
 				dest.setValue(s);

Modified: trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadStructured.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadStructured.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/ReadStructured.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -100,13 +100,13 @@
 	private void setValue(DSHandle dest, String s) throws ExecutionException {
 		try {
 			if (dest.getType().equals(Types.INT)) {
-				dest.setValue(new Double(Integer.parseInt(s.trim())));
+				dest.setValue(Integer.valueOf(s.trim()));
 			}
 			else if (dest.getType().equals(Types.FLOAT)) {
 				dest.setValue(new Double(s.trim()));
 			}
 			else if (dest.getType().equals(Types.BOOLEAN)) {
-				dest.setValue(new Boolean(s.trim()));
+				dest.setValue(Boolean.valueOf(s.trim()));
 			}
 			else if (dest.getType().equals(Types.STRING)) {
 				dest.setValue(s);

Modified: trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Sprintf.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Sprintf.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/karajan/lib/swiftscript/Sprintf.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -175,8 +175,8 @@
     private static void append_i(DSHandle arg, StringBuilder output) 
     throws ExecutionException {
         if (arg.getType() == Types.INT) {
-        	Double d = (Double) arg.getValue();
-            output.append(new Integer(d.intValue()));
+        	Integer d = (Integer) arg.getValue();
+            output.append(d);
         }
         else {
             throw new ExecutionException

Modified: trunk/src/org/griphyn/vdl/mapping/AbstractDataNode.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/AbstractDataNode.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/AbstractDataNode.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -193,13 +193,16 @@
         }
         try {
             DSHandle handle = getField(path.getFirst());
+            
             if (path.size() > 1) {
                 return handle.getField(path.butFirst());
             }
-            return handle;
+            else {
+                return handle;
+            }
         }
         catch (NoSuchFieldException e) {
-            logger.warn("could not find variable: " + field.getName() + 
+            logger.warn("could not find variable: " + field.getId() + 
                                " " + path);
             throw new InvalidPathException(path, this);
         }
@@ -216,24 +219,16 @@
             fields.add(this);
         }
         else {
-            Path rest = path.butFirst();
             if (path.isWildcard(0)) {
-                if (isArray() && !closed) {
-                    throw new FutureNotYetAvailable(getFutureWrapper());
-                }
-                for (DSHandle handle : handles.values()) {
-                    ((AbstractDataNode) handle).getFields(fields, rest);
-                }
+                throw new InvalidPathException("getFields([*]) only applies to arrays");
             }
-            else {
-                try {
-                    ((AbstractDataNode) getField(path.getFirst())).getFields(
-                        fields, rest);
-                }
-                catch (NoSuchFieldException e) {
-                    throw new InvalidPathException(path, this);
-                }
+            try {
+                ((AbstractDataNode) getField(path.getFirst())).getFields(
+                    fields, path.butFirst());
             }
+            catch (NoSuchFieldException e) {
+                throw new InvalidPathException(path, this);
+            }
         }
     }
 
@@ -251,70 +246,79 @@
              */
             throw new RuntimeException("Can't set root data node!");
         }
-        ((AbstractDataNode) getParent()).setField(field.getName(), handle);
+        ((AbstractDataNode) getParent()).setField(field.getId(), handle);
     }
 
-    protected void setField(String name, DSHandle handle) {
+    protected void setField(Comparable<?> id, DSHandle handle) {
         synchronized (handles) {
-            handles.put(name, handle);
+            handles.put(id, handle);
         }
     }
 
-    protected synchronized DSHandle getField(String name)
-    throws NoSuchFieldException {
-        DSHandle handle = getHandle(name);
-        if (handle == null) {
-            if (closed) {
-                throw new NoSuchFieldException(name);
+    protected DSHandle getField(Comparable<?> key)
+        throws NoSuchFieldException {
+        synchronized(handles) {
+            DSHandle handle = handles.get(key);
+            if (handle == null) {
+                if (closed) {
+                    throw new NoSuchFieldException(key.toString());
+                }
+                handle = createField(key);
             }
-            handle = createDSHandle(name);
+            return handle;
         }
-        return handle;
     }
 
-    protected DSHandle getHandle(String name) {
-        synchronized (handles) {
-            return handles.get(name);
-        }
-    }
-
     protected boolean isHandlesEmpty() {
         synchronized (handles) {
             return handles.isEmpty();
         }
     }
 
-    public DSHandle createDSHandle(String fieldName)
+    public DSHandle createField(Comparable<?> key)
     throws NoSuchFieldException {
         if (closed) {
             throw new RuntimeException("Cannot write to closed handle: " + this
-                + " (" + fieldName + ")");
+                + " (" + key + ")");
         }
-
-        AbstractDataNode child;
-        Field childField = getChildField(fieldName);
-        if (childField.getType().isArray()) {
-            child = new ArrayDataNode(getChildField(fieldName), getRoot(), this);
-        }
-        else {
-            child = new DataNode(getChildField(fieldName), getRoot(), this);
-        }
-
+        
+        return addHandle(key, newNode(getChildField(key)));
+    }
+    
+    protected DSHandle addHandle(Comparable<?> id, DSHandle handle) {
         synchronized (handles) {
-            Object o = handles.put(fieldName, child);
+            Object o = handles.put(id, handle);
             if (o != null) {
                 throw new RuntimeException(
                     "Trying to create a handle that already exists ("
-                    + fieldName + ") in " + this);
+                    + id + ") in " + this);
             }
         }
-        return child;
+        return handle;
     }
+    
+    protected AbstractDataNode newNode(Field f) {
+        if (f.getType().isArray()) {
+            return new ArrayDataNode(f, getRoot(), this);
+        }
+        else {
+            return new DataNode(f, getRoot(), this);
+        }
 
-    protected Field getChildField(String fieldName) throws NoSuchFieldException {
-        return Field.Factory.createField(fieldName, field.getType().getField(
-            fieldName).getType());
     }
+        
+    protected Field getChildField(Comparable<?> key) throws NoSuchFieldException {
+        if (getType().isArray()) {
+            return Field.Factory.createField(key, getType().itemType());
+        }
+        else {
+            return Field.Factory.createField(key, getType().getField((String) key).getType());
+        }
+    }
+    
+    protected Field getArrayChildField(Comparable<?> key) {
+        return Field.Factory.createField(key, getType().itemType());
+    }
 
     protected void checkDataException() {
         if (value instanceof DependentException) {
@@ -366,43 +370,39 @@
         getFringePaths(list, Path.EMPTY_PATH);
         return list;
     }
-
+    
     public void getFringePaths(List<Path> list, Path parentPath)
     throws HandleOpenException {
         checkMappingException();
-        if (getField().getType().getBaseType() != null) {
+        if (getType().getBaseType() != null) {
             list.add(Path.EMPTY_PATH);
         }
         else {
-            for (Field field : getField().getType().getFields()) {
-                AbstractDataNode mapper;
-                String name = field.getName();
+            for (Field field : getType().getFields()) {
+                AbstractDataNode child;
+                String name = (String) field.getId();
                 try {
-                    mapper = (AbstractDataNode) this.getField(name);
+                    child = (AbstractDataNode) this.getField(name);
                 }
                 catch (NoSuchFieldException e) {
                     throw new RuntimeException
                     ("Inconsistency between type declaration and " + 
                         "handle for field '" + name + "'");
                 }
-                // [m] Hmm. Should there be a difference between field and
-                // mapper.getField()?
-                // Path fullPath =
-                // parentPath.addLast(mapper.getField().getName());
-                Path fullPath = parentPath.addLast(field.getName());
-                Type type = mapper.field.getType(); 
+                Path fullPath = parentPath.addLast(name);
+                Type type = child.getType(); 
                 if (!type.isPrimitive() &&
-                        !mapper.isArray() && 
+                        !child.isArray() && 
                         type.getFields().size() == 0) {
                     list.add(fullPath);
                 }
                 else {
-                    mapper.getFringePaths(list, fullPath);
+                    child.getFringePaths(list, fullPath);
                 }
             }
         }
     }
-
+    
     public void closeShallow() {
         synchronized(this) {
             if (this.closed) {
@@ -560,7 +560,7 @@
             Path myPath;
             if (parent != null) {
                 myPath = parent.getPathFromRoot();
-                pathFromRoot = myPath.addLast(getField().getName(), parent
+                pathFromRoot = myPath.addLast(getField().getId(), parent
                     .getField().getType().isArray());
             }
             else {
@@ -636,7 +636,7 @@
                 ((AbstractDataNode) h).clean();
             }
         }
-        else {
+        else if (!getType().isArray()) {
             Mapper mapper = getRoot().getMapper();
             if (mapper != null) {
                 mapper.clean(getPathFromRoot());

Modified: trunk/src/org/griphyn/vdl/mapping/ArrayDataNode.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/ArrayDataNode.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/ArrayDataNode.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -27,7 +27,7 @@
 		synchronized (handles) {
 			for (Map.Entry<Comparable<?>, DSHandle> e : handles.entrySet()) {
 				AbstractDataNode mapper = (AbstractDataNode) e.getValue();
-				Path fullPath = parentPath.addLast(e.getKey().toString(), getType().isArray());
+				Path fullPath = parentPath.addLast(e.getKey(), getType().isArray());
 				if (mapper.getType().isComposite()) {
 					mapper.getFringePaths(list, fullPath);
 				}
@@ -51,7 +51,6 @@
             }
         }
     }
-
 	
 	public boolean isArray() {
 		return true;
@@ -62,25 +61,32 @@
 	}
 	
     @Override
-    protected void setField(String name, DSHandle handle) {
-        super.setField(name, handle);
-        addKey(name);
+    protected void setField(Comparable<?> id, DSHandle handle) {
+        synchronized(getHandles()) {
+            super.setField(id, handle);
+            // Operations on the handles and the wrapper keys need to be synchronized.
+            // When a wrapper is created, it populates its list of keys with the handles
+            // available. If this happens concurrently with a call being exactly at this
+            // point in the code, then it's possible for a key to have both been added
+            // as part of the creation of the wrapper as well as due to the next call,
+            // causing duplicate iterations.
+            addKey(id);
+        }
     }
     
-    private void addKey(String name) {
-        synchronized(this) {
-            if (wrapper != null) {
-                ((ArrayIndexFutureList) wrapper).addKey(name);
-            }
+    private void addKey(Comparable<?> key) {
+        if (wrapper != null) {
+            ((ArrayIndexFutureList) wrapper).addKey(key);
         }
     }
-
+    
     @Override
-    public DSHandle createDSHandle(String fieldName)
-            throws NoSuchFieldException {
-        DSHandle h = super.createDSHandle(fieldName);
-        addKey(fieldName);
-        return h;
+    public DSHandle createField(Comparable<?> key) throws NoSuchFieldException {
+        synchronized(getHandles()) {
+            DSHandle h = super.createField(key);
+            addKey(key);
+            return h;
+        }
     }
 
     @Override
@@ -95,4 +101,30 @@
     public FutureList getFutureList() {
         return (FutureList) getFutureWrapper();
     }
+    
+    protected void getFields(List<DSHandle> fields, Path path) throws InvalidPathException {
+        if (path.isEmpty()) {
+            fields.add(this);
+        }
+        else {
+            Path rest = path.butFirst();
+            if (path.isWildcard(0)) {
+                if (!isClosed()) {
+                    throw new FutureNotYetAvailable(getFutureWrapper());
+                }
+                for (DSHandle handle : getHandles().values()) {
+                    ((AbstractDataNode) handle).getFields(fields, rest);
+                }
+            }
+            else {
+                try {
+                    ((AbstractDataNode) getField(path.getKey(0))).getFields(
+                        fields, path.butFirst());
+                }
+                catch (NoSuchFieldException e) {
+                    throw new InvalidPathException(path, this);
+                }
+            }
+        }
+    }
 }

Modified: trunk/src/org/griphyn/vdl/mapping/DSHandle.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/DSHandle.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/DSHandle.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -30,7 +30,7 @@
      */
     public Type getType();
 
-    public void init(Map<String,Object> params);
+    public void init(Map<String, Object> params);
 
     public DSHandle getRoot();
 
@@ -55,8 +55,8 @@
     public void setValue(Object value);
 
     /** create a new logical component */
-    public DSHandle createDSHandle(String fieldName) throws NoSuchFieldException;
-
+    public DSHandle createField(Comparable<?> key) throws NoSuchFieldException;
+ 
     // special file oriented methods, not sure if these apply to 
     // all datasets
 

Modified: trunk/src/org/griphyn/vdl/mapping/DataNode.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/DataNode.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/DataNode.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -12,6 +12,9 @@
 	
 	protected DataNode(Field field, DSHandle root, DSHandle parent) {
 		super(field);
+		if (parent != null && field.getId() == null) {
+		    throw new IllegalArgumentException("Internal error: field id is null");
+		}
 		this.root = root;
 		this.parent = parent;
 	}

Modified: trunk/src/org/griphyn/vdl/mapping/InvalidPathException.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/InvalidPathException.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/InvalidPathException.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -12,4 +12,8 @@
 	public InvalidPathException(Path path, DSHandle source) {
 		this(path.toString(), source);
 	}
+
+    public InvalidPathException(String string) {
+        super(string);
+    }
 }

Modified: trunk/src/org/griphyn/vdl/mapping/Path.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/Path.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/Path.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -12,7 +12,7 @@
 
 public class Path {
 	public static final Path EMPTY_PATH = new EmptyPath();
-	public static final Path CHILDREN = Path.parse("*");
+	public static final Path CHILDREN = Path.parse("[*]");
 
 	/** A list of Path.Entry that represents the path. */
 	private List<Path.Entry> entries;
@@ -48,13 +48,13 @@
 		/**
 		 * The name of this path entry (either the array offset or the type
 		 * member name.
-		 */
-		private String name;
+		 */		
+		private Comparable<?> key;
 
-		public Entry(String name, boolean index) {
-			this.name = name;
+		public Entry(Comparable<?> key, boolean index) {
+		    this.key = key;
 			this.index = index;
-			if (name == null) {
+			if (key == null) {
 				throw new IllegalArgumentException(
 						"Attempted to create a path entry with a null name");
 			}
@@ -72,75 +72,59 @@
 		}
 
 		public boolean isWildcard() {
-			return (name.length() == 1) && (name.charAt(0) == '*');
+		    return false;
 		}
 
-		public String getName() {
-			return name;
+		public Comparable<?> getKey() {
+			return key;
 		}
 
 		public boolean equals(Object obj) {
 			if (obj instanceof Entry) {
 				Entry other = (Entry) obj;
-				return name.equals(other.name) && (index == other.index);
+				if (isWildcard()) {
+				    return other.isWildcard();
+				}
+				return key.equals(other.key);
 			}
             return false;
 		}
 
 		public int hashCode() {
-			return name.hashCode() + (index ? 0 : 123);
+		    return key.hashCode() + (index ? 0 : 123);
 		}
 
 		public String toString() {
 			if (index) {
-				return '[' + name + ']';
+				return '[' + String.valueOf(key) + ']';
 			}
-            return name;
+			else {
+			    return String.valueOf(key);
+			}
 		}
+		
+		/*
+		 * equals() and hashCode() cannot be used to
+		 * properly test equality between a wildcard and 
+		 * another entry
+		 */
+		public static class Wildcard extends Entry {
+            @Override
+            public boolean isIndex() {
+                return true;
+            }
+
+            @Override
+            public boolean isWildcard() {
+                return true;
+            }
+            
+            
+		}
 	}
 
 	public static Path parse(String path) {
-		if (path == null || path.equals("") || path.equals("$")) {
-			return Path.EMPTY_PATH;
-		}
-		ArrayList<Entry> list = new ArrayList<Entry>();
-		StringBuilder sb = new StringBuilder();
-		Entry e = new Entry();
-		boolean wildcard = false;
-		for (int i = 0; i < path.length(); i++) {
-			char c = path.charAt(i);
-			switch (c) {
-				case '[': {
-					if (sb.length() == 0) {
-						continue; // TODO: what case does this capture?
-						// attempt to use multidim arrays?
-						//[m] it may simply be incomplete/incorrect
-					}
-				}
-				case '.': {
-					e.name = sb.toString();
-					list.add(e);
-					e = new Entry();
-					sb.setLength(0);
-					break;
-				}
-				case ']': {
-					e.index = true;
-					break;
-				}
-				case '*': {
-					wildcard = true;
-				}
-				default: {
-					sb.append(c);
-					break;
-				}
-			}
-		}
-		e.name = sb.toString();
-		list.add(e);
-		list.trimToSize();
-		return new Path(list, wildcard);
+		return new PathParser(path).parse();
 	}
 
 	private Path(List<Entry> entries, boolean wildcard) {
@@ -148,7 +132,7 @@
 		this.wildcard = wildcard;
 	}
 
-	private Path(List<Entry> entries) {
+	protected Path(List<Entry> entries) {
 		this(entries, false);
 		for (Entry e : entries) {
 			if (e.isWildcard()) {
@@ -170,20 +154,24 @@
 	    this.entries = Collections.emptyList();
 	}
 	
-	public String getElement(int index) {
-		return entries.get(index).name;
+	public Comparable<?> getElement(int index) {
+		return entries.get(index).key;
 	}
+	
+	public Comparable<?> getKey(int index) {
+        return entries.get(index).key;
+    }
 
 	public int size() {
 		return entries == null ? 0 : entries.size();
 	}
 
-	public String getFirst() {
-		return entries.get(0).name;
+	public Comparable<?> getFirst() {
+		return entries.get(0).key;
 	} 
 	
-	public String getLast() {
-		return entries.get(entries.size() - 1).name;
+	public Comparable<?> getLast() {
+		return entries.get(entries.size() - 1).key;
 	}
 
 	public boolean isEmpty() {
@@ -202,7 +190,7 @@
 		return new Path(entries.subList(fromIndex, toIndex));
 	}
 
-	public Path addFirst(String element, boolean index) {
+	public Path addFirst(Comparable<?> element, boolean index) {
 		Path p = new Path(this);
 		Entry e;
 		p.entries.add(0, e = new Entry(element, index));
@@ -216,7 +204,7 @@
 		return addFirst(element, false);
 	}
 
-	public Path addLast(String element, boolean index) {
+	public Path addLast(Comparable<?> element, boolean index) {
 		Path p = new Path(this);
 		Entry e = new Entry(element, index);
 		p.entries.add(e);
@@ -225,8 +213,15 @@
 		}
 		return p;
 	}
+	
+	protected void addLast(Entry e) {
+	    if (entries.isEmpty()) {
+	        entries = new ArrayList<Entry>();
+	    }
+	    entries.add(e);
+	}
 
-	public Path addLast(String element) {
+	public Path addLast(Comparable<?> element) {
 		return addLast(element, false);
 	}
 
@@ -239,18 +234,59 @@
 	public String stringForm() {
 		StringBuilder sb = new StringBuilder();
 		Iterator<Entry> i = entries.iterator();
+		boolean first = true;
 		while (i.hasNext()) {
-			sb.append(i.next().name);
-			if (i.hasNext()) {
-				sb.append('.');
-			}
+		    Entry e = i.next();
+		    if (e.isWildcard()) {
+		        sb.append("[*]");
+		    }
+		    else if (e.isIndex()) {
+		        sb.append('[');
+		        sb.append(stringForm(e.key));
+		        sb.append(']');
+		    }
+		    else {
+		        if (!first) {
+		            sb.append('.');
+		        }
+		        sb.append(e.key);
+		    }
+		    first = false;
 		}
 		return sb.toString();
 	}
 
+	private String stringForm(Comparable<?> key) {
+        if (key instanceof String) {
+            return "\"" + escape((String) key) + '"';
+        }
+        else if (key instanceof Number) {
+            return key.toString();
+        }
+        else {
+            throw new IllegalArgumentException("Unsupported key type: " + key);
+        }
+    }
+
 	/**
+	 * TODO: match or use the actual language valid escapes
+	 */
+    private String escape(String key) {
+        StringBuilder sb = new StringBuilder();
+        
+        for (int i = 0; i < key.length(); i++) {
+            char c = key.charAt(i);
+            if (c == '\\' || c == '"') {
+                sb.append('\\');
+            }
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    /**
 	 * Returns a human readable string representation of this path. The string
-	 * returned by this method <strong>will not</strong> correctly be parsed
+	 * returned by this method <strong>will not necessarily</strong> correctly be parsed
 	 * into the same path by {@link Path.parse}. In other words no guarantee is
 	 * made that <code>Path.parse(somePath.toString()).equals(somePath)</code>.
 	 * For a consistent such representation of this path use {@link stringForm}.
@@ -261,17 +297,23 @@
 	    }
 		StringBuffer sb = new StringBuffer();
 		
+		boolean first = true;
 		for (Entry e : entries) {
-			
-			if (e.isIndex()) {
+		    if (e.isWildcard()) {
+                sb.append("[*]");
+            }
+		    else if (e.isIndex()) {
 				sb.append('[');
-				sb.append(e.getName());
+				sb.append(e.getKey());
 				sb.append(']');
 			}
 			else {
-				sb.append('.');
-				sb.append(e.getName());
+			    if (!first) {
+			        sb.append('.');
+			    }
+				sb.append(e.getKey());
 			}
+		    first = false;
 		}
 		return tostrcached = sb.toString();
 	}

Added: trunk/src/org/griphyn/vdl/mapping/PathComparator.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/PathComparator.java	                        (rev 0)
+++ trunk/src/org/griphyn/vdl/mapping/PathComparator.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Jul 22, 2011
+ */
+package org.griphyn.vdl.mapping;
+
+import java.util.Comparator;
+
+public class PathComparator implements Comparator<Path> {
+    @SuppressWarnings("unchecked")
+    public int compare(Path p1, Path p2) {
+        for (int i = 0; i < Math.min(p1.size(), p2.size()); i++) {
+            int d; 
+            d = indexOrder(p1.isArrayIndex(i), p2.isArrayIndex(i));
+            if (d != 0) {
+                return d;
+            }
+            Comparable<Object> e1 = (Comparable<Object>) p1.getElement(i);
+            Comparable<Object> e2 = (Comparable<Object>) p2.getElement(i);
+            if (p1.isArrayIndex(i)) {
+                if (e1.getClass() != e2.getClass()) {
+                    d = e1.getClass().getName().compareTo(e2.getClass().getName());
+                    
+                }
+            }
+            if (d == 0) {
+                d = e1.compareTo(e2);
+            }
+            if (d != 0) {
+                return d;
+            }
+        }
+        //the longer one wins
+        return p1.size() - p2.size();
+    }
+    
+    private int indexOrder(boolean i1, boolean i2) {
+        //it doesn't matter much what the order between indices and non-indices is,
+        //but it needs to be consistent
+        if (i1) {
+            if (!i2) {
+                return -1;
+            }
+        }
+        else {
+            if (i2) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+}
\ No newline at end of file

Added: trunk/src/org/griphyn/vdl/mapping/PathElementComparator.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/PathElementComparator.java	                        (rev 0)
+++ trunk/src/org/griphyn/vdl/mapping/PathElementComparator.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -0,0 +1,30 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Jul 22, 2011
+ */
+package org.griphyn.vdl.mapping;
+
+import java.util.Comparator;
+
+public class PathElementComparator implements Comparator<Comparable<?>> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public int compare(Comparable<?> p1, Comparable<?> p2) {
+        Comparable<Object> e1 = (Comparable<Object>) p1;
+        Comparable<Object> e2 = (Comparable<Object>) p2;
+        int d = 0;
+        if (e1.getClass() != e2.getClass()) {
+            d = e1.getClass().getName().compareTo(e2.getClass().getName());
+        }
+        if (d == 0) {
+            d = e1.compareTo(e2);
+        }
+        return d;
+    }
+}

Added: trunk/src/org/griphyn/vdl/mapping/PathParser.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/PathParser.java	                        (rev 0)
+++ trunk/src/org/griphyn/vdl/mapping/PathParser.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -0,0 +1,307 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Jul 21, 2011
+ */
+package org.griphyn.vdl.mapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.griphyn.vdl.mapping.Path.Entry;
+
+public class PathParser {
+    private String str;
+    private int crt = 0;
+    
+    public PathParser(String str) {
+        this.str = str;
+    }
+    
+    /*
+     *  path = emptyPath | nonEmptyPath
+     *  emptyPath = <nothing> | '$'
+     *  nonEmptyPath = element['.' field|indexElement]*
+     *  element = field | indexElement
+     *  indexElement = '[' index ']'
+     *  index = number | '"' string '"' | wildcard
+     *  wildcard = '*'
+     *  # TODO: this would need to be modified to include complex objects if
+     *  # supported as array keys
+     *  number = [+|-]('.' digit+)|(digit+['.' digit+])
+     *  digit = '0' - '9'
+     *  string = (character | escapeSequence)*
+     *  escapeSequence = '\' ('\' | '"' | 'n' | 't')
+     *  id = idFirstChar [idChar]
+     *  idFirstChar = 'a' - 'z' | 'A' - 'Z' | '_'
+     *  idChar = idFirstChar | digit 
+     */
+    public Path parse() {
+        return path();
+    }
+
+    private Path path() {
+        if (str.length() == 0 || str.equals("$")) {
+            return Path.EMPTY_PATH;
+        }
+        else {
+            return nonEmptyPath();
+        }
+    }
+
+    private Path nonEmptyPath() {
+        List<Path.Entry> l = new ArrayList<Path.Entry>();
+        l.add(element());
+        while (!done()) {
+            if (matchChar('[')) {
+                l.add(arrayElement());
+            }
+            else {
+                expect('.');
+                l.add(field());
+            }
+        }
+        return new Path(l);
+    }
+    
+    private Entry element() {
+       if (matchChar('[')) {
+           return arrayElement();
+       }
+       else {
+           return field();
+       }
+    }
+    
+    private Entry field() {
+        return new Path.Entry(id(), false);
+    }
+
+    private Entry arrayElement() {
+        Path.Entry index = index();
+        expect(']');
+        return index;
+    }
+
+    private Comparable<?> id() {
+        int start = crt;
+        expectIdFirstChar();
+        
+        while (idChar()) {
+            crt++;
+        }
+        return str.substring(start, crt);
+    }
+
+    private boolean idChar() {
+        if (crt >= str.length()) {
+            return false;
+        }
+        char c = str.charAt(crt);
+        return isLetter(c) || c == '_' || isDigit(c);
+    }
+
+    private void expectIdFirstChar() {
+        checkCrt();
+        char c = str.charAt(crt);
+        if (isLetter(c) || (c == '_')) {
+            crt++;
+        }
+        else {
+            throw invalidPath("Unexpected character '" + c + "'");
+        }
+    }
+    
+    private boolean isLetter(char c) {
+        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+    }
+    
+    private boolean isDigit(char c) {
+        return (c >= '0' && c <= '9');
+    }
+
+    private Path.Entry index() {
+        if (matchChar('"')) {
+            String s = string();
+            expect('"');
+            return new Path.Entry(s, true);
+        }
+        else if (matchChar('*')) {
+            return new Path.Entry.Wildcard();
+        }
+        else {
+            return new Path.Entry(number(), true);
+        }
+    }
+
+    private String string() {
+        StringBuilder sb = new StringBuilder();
+        while (!matchChar('"')) {
+            checkCrt();
+            char c = str.charAt(crt++);
+            if (c == '\\') {
+                checkCrt();
+                c = str.charAt(crt++);
+                switch(c) {
+                    case '"':
+                        c = '"';
+                        break;
+                    case '\\':
+                        c = '\\';
+                        break;
+                    case 'n':
+                        c = '\n';
+                        break;
+                    case 't':
+                        c = '\t';
+                        break;
+                    default:
+                        throw invalidPath("Illegal escape sequence '\\" + c + "'"); 
+                }
+            }
+            sb.append(c);
+        }
+        crt--;
+        return sb.toString();
+    }
+
+    /*
+     * number = [+|-]('.' digit+)|(digit+['.' digit+])
+     */
+    private Comparable<?> number() {
+        checkCrt();
+        int start = crt;
+        skip('-');
+        skip('+');
+        boolean fp = false;
+        if (matchChar('.')) {
+            fp = true;
+            digits();
+        }
+        else {
+            digits();
+            if (matchChar('.')) {
+                fp = true;
+                digits();
+            }
+        }
+        if (fp) {
+            return Double.parseDouble(str.substring(start, crt));
+        }
+        else {
+            return Integer.parseInt(str.substring(start, crt));
+        }
+    }
+
+    private void digits() {
+        checkCrt();
+        char c = str.charAt(crt++);
+        if (!isDigit(c)) {
+            throw invalidPath("Expected digit but got '" + c + "'");
+        }
+        while (crt < str.length() && isDigit(str.charAt(crt))) {
+            crt++;
+        }
+    }
+
+    private void expect(char c) {
+        checkCrt();
+        if (!matchChar(c)) {
+            throw invalidPath("Expected '" + c + "'");
+        }
+    }
+
+    private boolean matchChar(char c) {
+        if (crt < str.length() && str.charAt(crt) == c) {
+            crt++;
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+    
+    private void skip(char c) {
+        if (crt < str.length() && str.charAt(crt) == c) {
+            crt++;
+        }
+    }
+
+    private void checkCrt() {
+        if (crt >= str.length()) {
+            throw new PathParsingException("Premature end of path");
+        }
+    }
+
+    private boolean done() {
+        return crt >= str.length();
+    }
+    
+    private PathParsingException invalidPath(String msg) {
+        return new PathParsingException(msg + " in \"" + str + "\" col " + (crt + 1));
+    }
+    
+    private static int failed, total;
+    
+    public static void main(String[] args) {
+        testCorrect("a");
+        testCorrect("a.b");
+        testCorrect("a[0]");
+        testCorrect("a[1.0]");
+        testCorrect("a.b.c");
+        testCorrect("a[\"string\"].c");
+        testCorrect("a[123].b[\"123\"].d");
+        testCorrect("[\"str\\\"rts\"]");
+        testCorrect("x[-.23]");
+        testCorrect("[*]");
+        testInvalid("b.-");
+        testInvalid("a[1");
+        testInvalid("a[\"aa]");
+        testInvalid("[\"invalid\\escape\"]");
+        System.out.println("Total tests: " + total + ", failed tests: " + failed);
+    }
+
+    private static void testInvalid(String p) {
+        total++;
+        try {
+            System.out.print(p + ":");
+            System.out.print(spaces(32 - p.length()));
+            System.out.println("FAILED: " + new PathParser(p).parse().stringForm());
+            failed++;
+        }
+        catch (PathParsingException e) {
+            System.out.println("OK: " + e.getMessage());
+        }
+    }
+
+    private static void testCorrect(String p) {
+        total++;
+        try {
+            System.out.print(p + ":");
+            System.out.print(spaces(32 - p.length()));
+            Path pp = new PathParser(p).parse();
+            if (pp.equals(new PathParser(pp.stringForm()).parse())) {
+                System.out.println("OK: " + pp.stringForm());
+            }
+            else {
+                System.out.println("FAILED2: " + pp.stringForm());
+            }
+        }
+        catch (PathParsingException e) {
+            System.out.println("FAILED: " + e.getMessage());
+            failed++;
+        }
+    }
+    
+    private static String spaces(int count) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < count; i++) {
+            sb.append(' ');
+        }
+        return sb.toString();
+    }
+}

Added: trunk/src/org/griphyn/vdl/mapping/PathParsingException.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/PathParsingException.java	                        (rev 0)
+++ trunk/src/org/griphyn/vdl/mapping/PathParsingException.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -0,0 +1,17 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Jul 22, 2011
+ */
+package org.griphyn.vdl.mapping;
+
+public class PathParsingException extends RuntimeException {
+
+    public PathParsingException(String msg) {
+        super(msg);
+    }
+}

Modified: trunk/src/org/griphyn/vdl/mapping/RootArrayDataNode.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/RootArrayDataNode.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/RootArrayDataNode.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -54,7 +54,7 @@
 		}
 		try {
 			mapper = MapperFactory.getMapper(desc, params);
-			getField().setName(PARAM_PREFIX.getStringValue(mapper));
+			getField().setId(PARAM_PREFIX.getStringValue(mapper));
 			initialized();
 			checkInputs();
 		}

Modified: trunk/src/org/griphyn/vdl/mapping/RootDataNode.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/RootDataNode.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/RootDataNode.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -61,7 +61,7 @@
 		}
 		try {
 			mapper = MapperFactory.getMapper(desc, params);
-			getField().setName(PARAM_PREFIX.getStringValue(mapper));
+			getField().setId(PARAM_PREFIX.getStringValue(mapper));
 			// initialized means that this data has its mapper initialized
 			// this should be called before checkInputs because the latter
 			// may trigger calls to things that try to access this data node's
@@ -150,15 +150,6 @@
 			// any number of indices is ok
 			try {
 			    for (DSHandle dh : handle.getFields(Path.CHILDREN)) {
-					Path path = dh.getPathFromRoot();
-					String index = path.getElement(path.size() - 1);
-					try {
-						Integer.parseInt(index);
-					}
-					catch (NumberFormatException nfe) {
-						throw new RuntimeException("Array element has index '" + index
-								+ "' that does not parse as an integer.");
-					}
 					checkConsistency(dh);
 				}
 			}

Modified: trunk/src/org/griphyn/vdl/mapping/file/AbstractFileMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/AbstractFileMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/AbstractFileMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -2,6 +2,8 @@
 
 import java.io.File;
 import java.io.FilenameFilter;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -9,6 +11,7 @@
 import java.util.Map;
 
 import org.apache.log4j.Logger;
+import org.globus.cog.util.Base64;
 import org.griphyn.vdl.mapping.AbsFile;
 import org.griphyn.vdl.mapping.AbstractDataNode;
 import org.griphyn.vdl.mapping.AbstractMapper;
@@ -117,21 +120,37 @@
 		int level = 0, tokenCount = path.size();
 		while (pi.hasNext()) {
 			Path.Entry nextPathElement = (Path.Entry) pi.next();
-			String token = nextPathElement.getName();
 			if (nextPathElement.isIndex()) {
-				if(logger.isDebugEnabled())
-					logger.debug("Mapping path component index "+token);
-				String f = getElementMapper().mapIndex(Integer.parseInt(token));
-				if(logger.isDebugEnabled())
-					logger.debug("field is mapped to: "+f);
-				sb.append(f);
+			    Comparable<?> key = nextPathElement.getKey();
+			    String f, token;
+			    if (key instanceof Integer) {
+			        token = key.toString();
+			        f = getElementMapper().mapIndex(((Integer) key).intValue());
+			    }
+			    else if (key instanceof Double) {
+			        token = Double.toHexString(((Double) key).doubleValue());
+			        f = getElementMapper().mapField(token);
+			    }
+			    else {
+			        MessageDigest md = getDigest();
+			        byte[] buf = md.digest(key.toString().getBytes());
+			        token = encode(buf);
+			        f = getElementMapper().mapField(token);
+			    }
+    			if (logger.isDebugEnabled()) {
+    			    logger.debug("Mapping path component to " + token);
+    			}
+    			sb.append(f);
 			}
 			else {
-				if(logger.isDebugEnabled())
-					logger.debug("Mapping path component field "+token);
+			    String token = (String) nextPathElement.getKey();
+				if (logger.isDebugEnabled()) {
+					logger.debug("Mapping path component field " + token);
+				}
 				String f = getElementMapper().mapField(token);
-				if(logger.isDebugEnabled())
-					logger.debug("field is mapped to: "+f);
+				if (logger.isDebugEnabled()) {
+					logger.debug("field is mapped to: " + f);
+				}
 				sb.append(f);
 			}
 
@@ -151,19 +170,39 @@
 		if (suffix != null) {
 			sb.append(suffix);
 		}
-		if(logger.isDebugEnabled())
-			logger.debug("mapper id="+this.hashCode()+" finished mapping "+path+" to "+sb.toString());
+		if (logger.isDebugEnabled()) {
+			logger.debug("mapper id=" + this.hashCode() + " finished mapping " 
+			    + path + " to " + sb.toString());
+		}
 		return new AbsFile(sb.toString());
 	}
 
-	public Collection existing() {
+	private String encode(byte[] buf) {
+        buf = Base64.encode(buf);
+        char[] c = new char[buf.length];
+        for (int i = 0; i < buf.length; i++) {
+            c[i] = (char) buf[i];
+        }
+        return String.copyValueOf(c);
+    }
+
+    private MessageDigest getDigest() {
+        try {
+            return MessageDigest.getInstance("SHA-1");
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw new Error("JVM error: SHA-1 not available");
+        }
+    }
+
+    public Collection<Path> existing() {
 		if(logger.isDebugEnabled())
 			logger.debug("list existing paths for mapper id="+this.hashCode());
 		final String location = PARAM_LOCATION.getStringValue(this);
 		final String prefix = PARAM_PREFIX.getStringValue(this);
 		final String suffix = PARAM_SUFFIX.getStringValue(this);
 		final String pattern = PARAM_PATTERN.getStringValue(this);
-		List l = new ArrayList();
+		List<Path> l = new ArrayList<Path>();
 		final AbsFile f;
 		if (location == null) {
 			f = new AbsFile(".");
@@ -286,7 +325,7 @@
 	  */
 	protected Path rmapElement(Path path, String e) {
 		if (Character.isDigit(e.charAt(0))) {
-			return path.addLast(String.valueOf(getElementMapper().rmapIndex(e)), true);
+			return path.addLast(getElementMapper().rmapIndex(e), true);
 		}
 		else {
 			return path.addLast(getElementMapper().rmapField(e));

Modified: trunk/src/org/griphyn/vdl/mapping/file/AirsnMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/AirsnMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/AirsnMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -29,7 +29,7 @@
 				else {
 					path = path.addLast("v");
 					path = path.addLast(
-							Integer.valueOf(tok.substring(tok.length() - 4)).toString(), true);
+							Integer.valueOf(tok.substring(tok.length() - 4)), true);
 				}
 			}
 			else {

Modified: trunk/src/org/griphyn/vdl/mapping/file/ArrayFileMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/ArrayFileMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/ArrayFileMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -31,7 +31,7 @@
 		Set<?> s = m.keySet();
 		Iterator<?> i = s.iterator();
 		while(i.hasNext()) {
-			String nextKey = i.next().toString();
+			Comparable<?> nextKey = (Comparable<?>) i.next();
 			l.add(Path.EMPTY_PATH.addLast(nextKey, true));
 		}
 		return l;

Modified: trunk/src/org/griphyn/vdl/mapping/file/CSVMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/CSVMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/CSVMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -158,7 +158,7 @@
 		int ii = 0;
 		while (itl.hasNext()) {
 			Path path = Path.EMPTY_PATH;
-			path = path.addFirst(String.valueOf(ii), true);
+			path = path.addFirst(ii, true);
 			List colContent = (List) itl.next();
 			Iterator itc = colContent.iterator();
 			int j = 0;
@@ -184,16 +184,16 @@
 
 		readFile();
 
-		Iterator pi = path.iterator();
-		Path.Entry pe = (Path.Entry) pi.next();
+		Iterator<Path.Entry> pi = path.iterator();
+		Path.Entry pe = pi.next();
 		if (!pe.isIndex()) {
 			return null;
 		}
 		int i = 0;
-		try {
-			i = Integer.parseInt(pe.getName());
+		if (pe.getKey() instanceof Integer) {
+		    i = ((Integer) pe.getKey()).intValue();
 		}
-		catch (NumberFormatException e) {
+		else {
 			return null;
 		}
 		if (i > content.size()) {
@@ -208,8 +208,8 @@
 			return new AbsFile((String) cl.get(0));
 		}
 
-		pe = (Path.Entry) pi.next();
-		String col = pe.getName();
+		pe = pi.next();
+		String col = String.valueOf(pe.getKey());
 		if (!colindex.containsKey(col)) {
 			return null;
 		}

Modified: trunk/src/org/griphyn/vdl/mapping/file/FileSystemArrayMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/FileSystemArrayMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/FileSystemArrayMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -8,17 +8,16 @@
 import org.griphyn.vdl.mapping.PhysicalFormat;
 
 public class FileSystemArrayMapper extends AbstractFileMapper {
-	private Map filenames = new HashMap();
+	private Map<Object, String> filenames = new HashMap<Object, String>();
 	private int count = 0;
 	
 	public Path rmap(String name) {
 		if (name == null || name.equals("")) {
 			return null;
 		}
-		String index = String.valueOf(count);
-		filenames.put(index, name);
+		filenames.put(count, name);
 		Path p = Path.EMPTY_PATH;
-		p = p.addFirst(index, true);
+		p = p.addFirst(count, true);
 		++count;
 		return p;
 	}
@@ -31,8 +30,8 @@
 			return null;
 		}
 		String location = PARAM_LOCATION.getStringValue(this);
-		String index = path.getFirst();
-		String filename = (String)filenames.get(index);
+		Object index = path.getFirst();
+		String filename = filenames.get(index);
 		if (filename == null) {
 			return null;
 		}

Modified: trunk/src/org/griphyn/vdl/mapping/file/FixedArrayFileMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/FixedArrayFileMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/FixedArrayFileMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -42,10 +42,10 @@
 		return (String[]) PARAM_FILES.getValue(this);
 	}
 
-	public Collection existing() {
-		List l = new ArrayList();
+	public Collection<Path> existing() {
+		List<Path> l = new ArrayList<Path>();
 		for (int i = 0; i < getFiles().length; i++) {
-			l.add(Path.EMPTY_PATH.addLast(String.valueOf(i), true));
+			l.add(Path.EMPTY_PATH.addLast(i, true));
 		}
 		return l;
 	}
@@ -55,8 +55,14 @@
 			throw new IllegalArgumentException(path.toString());
 		}
 		else {
-			int index = Integer.parseInt(path.getFirst());
-			return new AbsFile(getFiles()[index]);
+		    Object o = path.getFirst();
+		    if (o instanceof Integer) {
+		        int index = ((Integer) o).intValue();
+		        return new AbsFile(getFiles()[index]);
+		    }
+		    else {
+		        throw new IllegalArgumentException("The fixed array mapper can only be used with an int key array");
+		    }
 		}
 	}
 

Modified: trunk/src/org/griphyn/vdl/mapping/file/ROIMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/ROIMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/ROIMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -38,9 +38,10 @@
 			String tok = st.nextToken();
 			if (i == 1 && tok.equals("ROI")) {
 				path = path.addLast("roi");
-				if (notseen)
+				if (notseen) {
 					idx = new Integer(count);
-				path = path.addLast(idx.toString(), true);
+				}
+				path = path.addLast(idx, true);
 				if (st.hasMoreElements()) {
 					i++;
 					continue;

Modified: trunk/src/org/griphyn/vdl/mapping/file/StructuredRegularExpressionMapper.java
===================================================================
--- trunk/src/org/griphyn/vdl/mapping/file/StructuredRegularExpressionMapper.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/mapping/file/StructuredRegularExpressionMapper.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -44,7 +44,7 @@
 		Collection output = new ArrayList();
 		Collection sourceFields;
 		try {
-			sourceFields = sourceHandle.getFields(Path.parse("[*]"));
+			sourceFields = sourceHandle.getFields(Path.CHILDREN);
 		}
 		catch (InvalidPathException ipe) {
 			return Collections.EMPTY_LIST;

Modified: trunk/src/org/griphyn/vdl/type/Field.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/Field.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/Field.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -7,13 +7,13 @@
 	 * get the name of the field
 	 * @return
 	 */
-	public String getName();
+	public Comparable<?> getId();
 	
 	/**
 	 * set the name of the field
 	 *
 	 */
-	public void setName(String name);
+	public void setId(Comparable<?> id);
 		
 	/**
 	 * get the type of the field
@@ -38,8 +38,8 @@
 			return new FieldImpl();
 		}
 		
-		public static Field createField(String name, Type type) {
-			return new FieldImpl(name, type);
+		public static Field createField(Comparable<?> id, Type type) {
+			return new FieldImpl(id, type);
 		}		
 	}
 }

Modified: trunk/src/org/griphyn/vdl/type/Type.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/Type.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/Type.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -52,7 +52,7 @@
 	public URI getNamespaceURI();
 
 	boolean isArray();
-	
+		
 	/**
 	 * Returns true if this type is a composite type (array or struct).
 	 */
@@ -134,7 +134,7 @@
 
 	/**
 	 * This method returns the type of the array consisting of elements of this
-	 * type.*
+	 * type and integer keys.
 	 */
 	Type arrayType();
 	
@@ -143,6 +143,11 @@
 	 * If t is a type, t == t.arrayType().itemType();
 	 */
 	Type itemType();
+	
+	/**
+	 * For an array, this returns the array key type
+	 */
+	Type keyType();
 
 	/**
 	 * A factory class with static methods for creating instances of Type.

Modified: trunk/src/org/griphyn/vdl/type/Types.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/Types.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/Types.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -2,31 +2,97 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
+import org.griphyn.vdl.type.impl.TypeImpl.Array;
+
 public abstract class Types {
 
 	//TODO: check namespace references in type definitions
 	private static Map<String, Type> types = 
 	    new HashMap<String, Type>();
+	
+	public synchronized static boolean isValidType(String name, Set<String> validTypes) {
+	    if (validTypes.contains(name) || types.containsKey(name)) {
+	        return true;
+	    }
+	    else {
+	        String[] names = getArrayTypeNames(name);
+	        if (names == null) {
+	            return false;
+	        }
+	        else {
+	            return isValidType(names[0], validTypes) && isValidType(names[1], validTypes);
+	        }
+	    }
+	}
+	
+	private static String[] getArrayTypeNames(String name) {
+	    if(name.endsWith("]")) {
+            int index = name.lastIndexOf('[');
+            if (index == -1) {
+                throw new RuntimeException("Malformed type name: " + name);
+            }
+            String keyTypeName = name.substring(index + 1, name.length() - 1);
+            String baseTypeName = name.substring(0, index);
+            if (keyTypeName.equals("")) {
+                keyTypeName = "int";
+            }
+            return new String[] {baseTypeName, keyTypeName};
+        }
+	    else {
+	        return null;
+	    }
+	}
+	
+	private static String getArrayComponentTypeName(String name, int index) {
+	    String[] names = getArrayTypeNames(name);
+        if (names == null) {
+            return null;
+        }
+        else {
+            return names[index];
+        }
+	}
+	
+	public static String normalize(String t) {
+        String[] names = getArrayTypeNames(t);
+        if (names == null) {
+            return t;
+        }
+        else {
+            return normalize(names[0]) + "[" + names[1] + "]";
+        }
+    }
+	
+	public static String getArrayItemTypeName(String name) {
+	    return getArrayComponentTypeName(name, 0);
+	}
+	
+	public static String getArrayIndexTypeName(String name) {
+        return getArrayComponentTypeName(name, 1);
+    }
 
 	public synchronized static Type getType(String name) throws NoSuchTypeException {
-		Type type = (Type) types.get(name);
+		Type type = types.get(name);
 		if (type == null) {
-			if(name.endsWith("[]")) {
-				String base = name.substring(0, name.length() - 2);
-				Type baseType = getType(base);
-				Type arrayType = baseType.arrayType();
+		    String[] names = getArrayTypeNames(name);
+		    if (names != null) {
+				Type baseType = getType(names[0]);
+				Type keyType = getType(names[1]);
+				Type arrayType = new Array(baseType, keyType);
 				addType(arrayType);
 				return arrayType;
-			} else {
-				throw new NoSuchTypeException(name);
 			}
+			else {
+                throw new NoSuchTypeException(name);
+            }
 		}
 		else {
 			return type;
 		}
 	}
-	
+		
 	public static boolean isPrimitive(String name) {
 	    try {
 	        Type t = getType(name);
@@ -48,7 +114,7 @@
 		return type;
 	}
 
-	public static final Type INT, STRING, FLOAT, BOOLEAN, ANY, EXTERNAL;
+	public static final Type INT, STRING, FLOAT, BOOLEAN, ANY, EXTERNAL, AUTO;
 
 	// add built-in primitive types
 	static {
@@ -58,13 +124,14 @@
 		BOOLEAN = addPrimitiveType("boolean");
 		ANY = addPrimitiveType("any");
 		EXTERNAL = addPrimitiveType("external");
+		AUTO = addPrimitiveType("auto");
 	}
 
 	public synchronized static void resolveTypes() throws NoSuchTypeException {
 		Map<String, Type> typesCopy = 
 		    new HashMap<String, Type>(types);
 		for (Map.Entry<String, Type> e : typesCopy.entrySet()) {
-			Type type = (Type) e.getValue();
+			Type type = e.getValue();
 			for (Field field : type.getFields()) {
 				Type resolved = getType(field.getType().getName());
 				field.setType(resolved);

Modified: trunk/src/org/griphyn/vdl/type/impl/FieldImpl.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/impl/FieldImpl.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/impl/FieldImpl.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -4,31 +4,31 @@
 import org.griphyn.vdl.type.Type;
 
 public class FieldImpl implements Field {
-	private String name = null;
-	private Type type = null;
+	private Comparable<?> id;
+	private Type type;
 	private boolean array = false;
 
 	public FieldImpl() {
 	}
 
-	public FieldImpl(String name, Type type, boolean array) {
-		this.name = name;
+	public FieldImpl(Comparable<?> id, Type type, boolean array) {
+		this.id = id;
 		this.type = type;
 		this.array = array;
 	}
 	
-	public FieldImpl(String name, Type type) {
-		this.name = name;
+	public FieldImpl(Comparable<?> id, Type type) {
+		this.id = id;
 		this.type = type;
 		this.array = false;
 	}
 	
-	public String getName() {
-		return name;
+	public Comparable<?> getId() {
+		return id;
 	}
 
-	public void setName(String name) {
-		this.name = name;
+	public void setId(Comparable<?> id) {
+		this.id = id;
 	}
 
 	public boolean isArray() {

Modified: trunk/src/org/griphyn/vdl/type/impl/TypeImpl.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/impl/TypeImpl.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/impl/TypeImpl.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -9,12 +9,13 @@
 import org.griphyn.vdl.type.DuplicateFieldException;
 import org.griphyn.vdl.type.Field;
 import org.griphyn.vdl.type.Type;
+import org.griphyn.vdl.type.Types;
 
 public class TypeImpl extends UnresolvedType {
 	private boolean primitive;
-	private Map fields;
+	private Map<String, Field> fields;
 	private Type baseType;
-
+	
 	public TypeImpl() {
 		this((URI) null, null, false);
 	}
@@ -31,7 +32,7 @@
 
 	private void init(boolean primitive) {
 		this.primitive = primitive;
-		fields = new HashMap();
+		fields = new HashMap<String, Field>();
 		baseType = null;
 	}
 
@@ -44,9 +45,10 @@
 	}
 
 	public void addField(Field field) throws DuplicateFieldException {
-		String name = field.getName();
-		if (name == null)
+		String name = (String) field.getId();
+		if (name == null) {
 			return;
+		}
 		if (fields.get(name) != null) {
 			throw new DuplicateFieldException(name);
 		}
@@ -65,7 +67,7 @@
 			throw new NullPointerException();
 		}
 
-		Field field = (Field) fields.get(name);
+		Field field = fields.get(name);
 		if (field != null) {
 			return field;
 		}
@@ -74,8 +76,8 @@
 		}
 	}
 
-	public List getFieldNames() {
-		ArrayList list = new ArrayList();
+	public List<String> getFieldNames() {
+		List<String> list = new ArrayList<String>();
 		list.addAll(fields.keySet());
 		return list;
 	}
@@ -83,13 +85,13 @@
 	public List<Field> getFields() {
 		return new ArrayList<Field>(fields.values());
 	}
-
-	public Type getBaseType() {
+	
+    public Type getBaseType() {
 		return baseType;
 	}
 
 	public Type arrayType() {
-		return new Array(this);
+		return new Array(this, Types.INT);
 	}
 
 	public Type itemType() {
@@ -113,15 +115,17 @@
         return isArray() || !fields.isEmpty();
     }
 
-    private static class Array extends TypeImpl {
+    public static class Array extends TypeImpl {
 		private Field field;
+		private Type keyType;
 
 		/** Constructs an array that will contain elements of the
 		    specified type. */
-		public Array(Type type) {
-			super(type.getNamespaceURI(), type.getName()+"[]", false);
+		public Array(Type valueType, Type keyType) {
+			super(valueType.getNamespaceURI(), valueType.getName()+"[" + keyType.getName() + "]", false);
 			field = Field.Factory.newInstance();
-			field.setType(type);
+			field.setType(valueType);
+			this.keyType = keyType;
 		}
 
 /*
@@ -141,5 +145,9 @@
 		public Type itemType() {
 			return field.getType();
 		}
+		
+		public Type keyType() {
+		    return keyType;
+		}
 	}
 }

Modified: trunk/src/org/griphyn/vdl/type/impl/UnresolvedType.java
===================================================================
--- trunk/src/org/griphyn/vdl/type/impl/UnresolvedType.java	2011-07-24 04:43:21 UTC (rev 4834)
+++ trunk/src/org/griphyn/vdl/type/impl/UnresolvedType.java	2011-07-24 23:04:11 UTC (rev 4835)
@@ -46,6 +46,10 @@
 	public Type itemType() {
 		throw new UnsupportedOperationException();
 	}
+	
+	public Type keyType() {
+	    throw new UnsupportedOperationException();
+	}
 
 	public Type getBaseType() {
 		throw new UnsupportedOperationException();
@@ -62,7 +66,7 @@
 	public List getFields() {
 		throw new UnsupportedOperationException("addField");
 	}
-
+	
 	public String getName() {
 		return name;
 	}




More information about the Swift-commit mailing list