You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2006/07/20 04:46:27 UTC

svn commit: r423723 - in /incubator/cayenne/main/trunk/cayenne/cayenne-java/src: cayenne/java/org/apache/cayenne/wocompat/ cayenne/java/org/apache/cayenne/wocompat/parser/ tests/java/org/apache/cayenne/wocompat/parser/

Author: aadamchik
Date: Wed Jul 19 19:46:26 2006
New Revision: 423723

URL: http://svn.apache.org/viewvc?rev=423723&view=rev
Log:
CAY-600

Added:
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PlistDataStructureFactory.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/DefaultPlistDataStructureFactory.java
Modified:
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PropertyListSerialization.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.jj
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/ParserTokenManager.java
    incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/wocompat/parser/PropertyListParserTst.java

Added: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PlistDataStructureFactory.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PlistDataStructureFactory.java?rev=423723&view=auto
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PlistDataStructureFactory.java (added)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PlistDataStructureFactory.java Wed Jul 19 19:46:26 2006
@@ -0,0 +1,33 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.wocompat;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * An interface that defines a factory for custom deserializing a property list.
+ */
+public interface PlistDataStructureFactory {
+
+    Map createMap(String keyPath);
+
+    Collection createCollection(String keyPath);
+}

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PropertyListSerialization.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PropertyListSerialization.java?rev=423723&r1=423722&r2=423723&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PropertyListSerialization.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/PropertyListSerialization.java Wed Jul 19 19:46:26 2006
@@ -25,169 +25,214 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.util.Collection;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.wocompat.parser.Parser;
 
 /**
- * A <b>PropertyListSerialization</b> is a utility class 
- * that reads and stores files in NeXT/Apple
- * property list format. Unlike corresponding WebObjects 
- * class, <code>PropertyListSerialization</code> uses standard
- * Java collections (lists and maps) to store property lists.
+ * A <b>PropertyListSerialization</b> is a utility class that reads and stores files in
+ * NeXT/Apple property list format. Unlike corresponding WebObjects class,
+ * <code>PropertyListSerialization</code> uses standard Java collections (lists and
+ * maps) to store property lists.
  * 
- * @author Andrei Adamchik
+ * @author Andrus Adamchik
  */
 public class PropertyListSerialization {
-	/**
-	 * Reads a property list file. Returns a property list object, that is
-	 * normally a java.util.List or a java.util.Map, but can also be a String
-	 * or a Number. 
-	 */
-	public static Object propertyListFromFile(File f) throws FileNotFoundException {
-		if (!f.isFile()) {
-			throw new FileNotFoundException("No such file: " + f);
-		}
-
-		return new Parser(f).propertyList();
-	}
-
-	/**
-	 * Reads a property list data from InputStream. Returns a property list o
-	 * bject, that is normally a java.util.List or a java.util.Map, 
-	 * but can also be a String or a Number. 
-	 */
-	public static Object propertyListFromStream(InputStream in) {
-		return new Parser(in).propertyList();
-	}
-
-	/**
-	 * Saves property list to file.
-	 */
-	public static void propertyListToFile(File f, Object plist) {
-		try {
-			BufferedWriter out = new BufferedWriter(new FileWriter(f));
-			try {
-				writeObject("", out, plist);
-			} finally {
-				out.close();
-			}
-		} catch (IOException ioex) {
-			throw new CayenneRuntimeException("Error saving plist.", ioex);
-		}
-	}
+
+    /**
+     * Reads a property list file. Returns a property list object, that is normally a
+     * java.util.List or a java.util.Map, but can also be a String or a Number.
+     */
+    public static Object propertyListFromFile(File f) throws FileNotFoundException {
+        return propertyListFromFile(f, null);
+    }
+
+    /**
+     * Reads a property list file. Returns a property list object, that is normally a
+     * java.util.List or a java.util.Map, but can also be a String or a Number.
+     */
+    public static Object propertyListFromFile(File f, PlistDataStructureFactory factory)
+            throws FileNotFoundException {
+        if (!f.isFile()) {
+            throw new FileNotFoundException("No such file: " + f);
+        }
+
+        return new Parser(f, factory).propertyList();
+    }
+
+    /**
+     * Reads a property list data from InputStream. Returns a property list o bject, that
+     * is normally a java.util.List or a java.util.Map, but can also be a String or a
+     * Number.
+     */
+    public static Object propertyListFromStream(InputStream in) {
+        return propertyListFromStream(in, null);
+    }
+
+    /**
+     * Reads a property list data from InputStream. Returns a property list o bject, that
+     * is normally a java.util.List or a java.util.Map, but can also be a String or a
+     * Number.
+     */
+    public static Object propertyListFromStream(
+            InputStream in,
+            PlistDataStructureFactory factory) {
+        return new Parser(in, factory).propertyList();
+    }
+
+    /**
+     * Saves property list to file.
+     */
+    public static void propertyListToFile(File f, Object plist) {
+        try {
+            BufferedWriter out = new BufferedWriter(new FileWriter(f));
+            try {
+                writeObject("", out, plist);
+            }
+            finally {
+                out.close();
+            }
+        }
+        catch (IOException ioex) {
+            throw new CayenneRuntimeException("Error saving plist.", ioex);
+        }
+    }
+
+    /**
+     * Saves property list to file.
+     */
+    public static void propertyListToStream(OutputStream os, Object plist) {
+        try {
+            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
+            try {
+                writeObject("", out, plist);
+            }
+            finally {
+                out.close();
+            }
+        }
+        catch (IOException ioex) {
+            throw new CayenneRuntimeException("Error saving plist.", ioex);
+        }
+    }
 
     /**
      * Internal method to recursively write a property list object.
      */
-	protected static void writeObject(String offset, Writer out, Object plist)
-		throws IOException {
-		if (plist == null) {
-			return;
-		}
-
-		if (plist instanceof List) {
-			List list = (List) plist;
-
-			out.write('\n');
-			out.write(offset);
-
-			if (list.size() == 0) {
-				out.write("()");
-				return;
-			}
-
-			out.write("(\n");
-
-			String childOffset = offset + "   ";
-			Iterator it = list.iterator();
-			boolean appended = false;
-			while (it.hasNext()) {
-				// Java collections can contain nulls, skip them
-				Object obj = it.next();
-				if (obj != null) {
-					if (appended) {
-						out.write(", \n");
-					}
-
-					out.write(childOffset);
-					writeObject(childOffset, out, obj);
-					appended = true;
-				}
-			}
-
-			out.write('\n');
-			out.write(offset);
-			out.write(')');
-		} else if (plist instanceof Map) {
-			Map map = (Map) plist;
-			out.write('\n');
-			out.write(offset);
-
-			if (map.size() == 0) {
-				out.write("{}");
-				return;
-			}
-
-			out.write("{");
-
-			String childOffset = offset + "    ";
-
-			Iterator it = map.entrySet().iterator();
-			while (it.hasNext()) {
-				// Java collections can contain nulls, skip them
-				Map.Entry entry = (Map.Entry) it.next();
-				Object key = entry.getKey();
-				if (key == null) {
-					continue;
-				}
-				Object obj = entry.getValue();
-				if (obj == null) {
-					continue;
-				}
-				out.write('\n');
-				out.write(childOffset);
-				out.write(quoteString(key.toString()));
-				out.write(" = ");
-				writeObject(childOffset, out, obj);
-				out.write(';');
-			}
-
-			out.write('\n');
-			out.write(offset);
-			out.write('}');
-		} else if (plist instanceof String) {
-			out.write(quoteString(plist.toString()));
-		} else if (plist instanceof Number) {
-			out.write(plist.toString());
-		} else {
-			throw new CayenneRuntimeException(
-				"Unsupported class for property list serialization: "
-					+ plist.getClass().getName());
-		}
-	}
-
-	/** 
-	 * Escapes all doublequotes and backslashes.
-	 */
-	protected static String escapeString(String str) {
-		char[] chars = str.toCharArray();
-		int len = chars.length;
-		StringBuffer buf = new StringBuffer(len + 3);
-
-		for (int i = 0; i < len; i++) {
-			if (chars[i] == '\"' || chars[i] == '\\') {
-				buf.append('\\');
-			}			
-			buf.append(chars[i]);
-		}
+    protected static void writeObject(String offset, Writer out, Object plist)
+            throws IOException {
+        if (plist == null) {
+            return;
+        }
 
-		return buf.toString();
-	}
+        if (plist instanceof Collection) {
+            Collection list = (Collection) plist;
+
+            out.write('\n');
+            out.write(offset);
+
+            if (list.size() == 0) {
+                out.write("()");
+                return;
+            }
+
+            out.write("(\n");
+
+            String childOffset = offset + "   ";
+            Iterator it = list.iterator();
+            boolean appended = false;
+            while (it.hasNext()) {
+                // Java collections can contain nulls, skip them
+                Object obj = it.next();
+                if (obj != null) {
+                    if (appended) {
+                        out.write(", \n");
+                    }
+
+                    out.write(childOffset);
+                    writeObject(childOffset, out, obj);
+                    appended = true;
+                }
+            }
+
+            out.write('\n');
+            out.write(offset);
+            out.write(')');
+        }
+        else if (plist instanceof Map) {
+            Map map = (Map) plist;
+            out.write('\n');
+            out.write(offset);
+
+            if (map.size() == 0) {
+                out.write("{}");
+                return;
+            }
+
+            out.write("{");
+
+            String childOffset = offset + "    ";
+
+            Iterator it = map.entrySet().iterator();
+            while (it.hasNext()) {
+                // Java collections can contain nulls, skip them
+                Map.Entry entry = (Map.Entry) it.next();
+                Object key = entry.getKey();
+                if (key == null) {
+                    continue;
+                }
+                Object obj = entry.getValue();
+                if (obj == null) {
+                    continue;
+                }
+                out.write('\n');
+                out.write(childOffset);
+                out.write(quoteString(key.toString()));
+                out.write(" = ");
+                writeObject(childOffset, out, obj);
+                out.write(';');
+            }
+
+            out.write('\n');
+            out.write(offset);
+            out.write('}');
+        }
+        else if (plist instanceof String) {
+            out.write(quoteString(plist.toString()));
+        }
+        else if (plist instanceof Number) {
+            out.write(plist.toString());
+        }
+        else {
+            throw new CayenneRuntimeException(
+                    "Unsupported class for property list serialization: "
+                            + plist.getClass().getName());
+        }
+    }
+
+    /**
+     * Escapes all doublequotes and backslashes.
+     */
+    protected static String escapeString(String str) {
+        char[] chars = str.toCharArray();
+        int len = chars.length;
+        StringBuffer buf = new StringBuffer(len + 3);
+
+        for (int i = 0; i < len; i++) {
+            if (chars[i] == '\"' || chars[i] == '\\') {
+                buf.append('\\');
+            }
+            buf.append(chars[i]);
+        }
+
+        return buf.toString();
+    }
 
     /**
      * Returns a quoted String, with all the escapes preprocessed. May return an unquoted
@@ -195,31 +240,31 @@
      * is the following:
      * 
      * <pre>
-     *      c &gt;= 'a' &amp;&amp; c &lt;= 'z'
-     *      c &gt;= 'A' &amp;&amp; c &lt;= 'Z'
-     *      c &gt;= '0' &amp;&amp; c &lt;= '9'
-     *      c == '_'
-     *      c == '$'
-     *      c == ':'
-     *      c == '.'
-     *      c == '/'
+     *       c &gt;= 'a' &amp;&amp; c &lt;= 'z'
+     *       c &gt;= 'A' &amp;&amp; c &lt;= 'Z'
+     *       c &gt;= '0' &amp;&amp; c &lt;= '9'
+     *       c == '_'
+     *       c == '$'
+     *       c == ':'
+     *       c == '.'
+     *       c == '/'
      * </pre>
      */
-	protected static String quoteString(String str) {
-		boolean shouldQuote = false;
-		
-		// scan string for special chars, 
+    protected static String quoteString(String str) {
+        boolean shouldQuote = false;
+
+        // scan string for special chars,
         // if we have them, string must be quoted
-        
-		String noQuoteExtras = "_$:./";
-		char[] chars = str.toCharArray();
-		int len = chars.length;
+
+        String noQuoteExtras = "_$:./";
+        char[] chars = str.toCharArray();
+        int len = chars.length;
         if (len == 0) {
             shouldQuote = true;
         }
-		for (int i = 0; !shouldQuote && i < len; i++) {
+        for (int i = 0; !shouldQuote && i < len; i++) {
             char c = chars[i];
-            
+
             if ((c >= 'a' && c <= 'z')
                     || (c >= 'A' && c <= 'Z')
                     || (c >= '0' && c <= '9')
@@ -230,7 +275,9 @@
             shouldQuote = true;
         }
 
-		str = escapeString(str);
-		return (shouldQuote) ? '\"' + str + '\"' : str;
-	}
+        str = escapeString(str);
+        return (shouldQuote) ? '\"' + str + '\"' : str;
+    }
+
+    
 }

Added: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/DefaultPlistDataStructureFactory.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/DefaultPlistDataStructureFactory.java?rev=423723&view=auto
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/DefaultPlistDataStructureFactory.java (added)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/DefaultPlistDataStructureFactory.java Wed Jul 19 19:46:26 2006
@@ -0,0 +1,38 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.wocompat.parser;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.wocompat.PlistDataStructureFactory;
+
+class DefaultPlistDataStructureFactory implements PlistDataStructureFactory {
+
+    public Collection createCollection(String keyPath) {
+        return new ArrayList();
+    }
+
+    public Map createMap(String keyPath) {
+        return new HashMap();
+    }
+}
\ No newline at end of file

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.java?rev=423723&r1=423722&r2=423723&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.java Wed Jul 19 19:46:26 2006
@@ -18,11 +18,13 @@
  *  under the License.
  ****************************************************************/
 
+
 package org.apache.cayenne.wocompat.parser;
 
 import org.apache.log4j.Logger;
 import java.io.*;
 import java.util.*;
+import org.apache.cayenne.wocompat.PlistDataStructureFactory;
 
 /**
  * NeXT/Apple Property List format parser. 
@@ -31,24 +33,37 @@
  * <a href="http://www.reportmill.com/">http://www.reportmill.com/</a></p>
  */
 public class Parser implements ParserConstants {
-
     private static Logger logObj = Logger.getLogger(Parser.class);
 
+    private PlistDataStructureFactory factory = new DefaultPlistDataStructureFactory();
+
     public Parser() {
-        this(System.in);
+        this(System.in, null);
     }
 
-    public Parser(String filename) throws FileNotFoundException {
-        this(new FileInputStream(filename));
+    public Parser(PlistDataStructureFactory factory) {
+        this(System.in, factory);
     }
 
-    public Parser(File f) throws FileNotFoundException {
-        this(new FileInputStream(f));
+    public Parser(String filename, PlistDataStructureFactory factory) throws FileNotFoundException {
+        this(new FileInputStream(filename), factory);
+    }
+
+    public Parser(File f, PlistDataStructureFactory factory) throws FileNotFoundException {
+        this(new FileInputStream(f), factory);
+    }
+
+    public Parser(InputStream in, PlistDataStructureFactory factory) {
+        this(in);
+
+        if(factory != null) {
+            this.factory = factory;
+        }
     }
 
     public Object propertyList() {
         try {
-            return object();
+            return object("");
         }
         catch (ParseException pe) {
            logObj.info("Error parsing plist", pe);
@@ -56,22 +71,39 @@
         }
     }
 
-public static void main(String args[]) {
-  Parser r = new Parser();
-  Object o = r.propertyList();
-  System.out.println(o);
-  }
+    /**
+     * @deprecated since 3.0, use 'object(String)' instead.
+     */
+    public Object object() throws ParseException {
+        return object("");
+    }
+
+    /**
+     * @deprecated since 3.0, use 'map(String)' instead.
+     */
+    public final java.util.HashMap dictionary()
+                                   throws ParseException {
+            return (java.util.HashMap) map("");
+    }
+
+    /**
+     * @deprecated since 3.0, use 'collection(String)' instead.
+     */
+    public final java.util.ArrayList array()
+                                   throws ParseException {
+            return (java.util.ArrayList) collection("");
+    }
 
-  final public Object object() throws ParseException {
+  final public Object object(String parentKeyPath) throws ParseException {
         Object node;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case 8:
-      node = array();
-                               {if (true) return node;}
+      node = collection(parentKeyPath);
+                                                 {if (true) return node;}
       break;
     case 10:
-      node = dictionary();
-                                    {if (true) return node;}
+      node = map(parentKeyPath);
+                                          {if (true) return node;}
       break;
     case INT:
     case FLOAT:
@@ -114,10 +146,10 @@
     throw new Error("Missing return statement in function");
   }
 
-  final public HashMap dictionary() throws ParseException {
-        HashMap h;
+  final public Map map(String parentKeyPath) throws ParseException {
+        Map h;
     jj_consume_token(10);
-              h = new HashMap();
+              h = factory.createMap(parentKeyPath);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case INT:
     case FLOAT:
@@ -125,14 +157,16 @@
     case 10:
     case STRING:
     case QUOTED_STRING:
-      keyValuePair(h);
+      keyValuePair(parentKeyPath, h);
       label_1:
       while (true) {
-        if (!jj_2_1(2)) {
+        if (jj_2_1(2)) {
+          ;
+        } else {
           break label_1;
         }
         jj_consume_token(13);
-        keyValuePair(h);
+        keyValuePair(parentKeyPath, h);
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case 13:
@@ -140,29 +174,31 @@
         break;
       default:
         jj_la1[2] = jj_gen;
+        ;
       }
       break;
     default:
       jj_la1[3] = jj_gen;
+      ;
     }
     jj_consume_token(11);
               {if (true) return h;}
     throw new Error("Missing return statement in function");
   }
 
-  final public void keyValuePair(Map map) throws ParseException {
+  final public void keyValuePair(String parentKeyPath, Map map) throws ParseException {
         Object key, val;
-    key = object();
+    key = object(parentKeyPath);
     jj_consume_token(7);
-    val = object();
-                                 map.put(key, val);
+    val = object(parentKeyPath + "." + key);
+                                                          map.put(key, val);
   }
 
-  final public ArrayList array() throws ParseException {
-  ArrayList v;
+  final public Collection collection(String parentKeyPath) throws ParseException {
+  Collection v;
   Object o;
     jj_consume_token(8);
-         v = new ArrayList();
+         v = factory.createCollection(parentKeyPath);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case INT:
     case FLOAT:
@@ -170,24 +206,26 @@
     case 10:
     case STRING:
     case QUOTED_STRING:
-      o = object();
-                   v.add(o);
+      o = object(parentKeyPath);
+                                v.add(o);
       label_2:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case 12:
+          ;
           break;
         default:
           jj_la1[4] = jj_gen;
           break label_2;
         }
         jj_consume_token(12);
-        o = object();
-                        v.add(o);
+        o = object(parentKeyPath);
+                                     v.add(o);
       }
       break;
     default:
       jj_la1[5] = jj_gen;
+      ;
     }
     jj_consume_token(9);
         {if (true) return v;}
@@ -201,6 +239,42 @@
     finally { jj_save(0, xla); }
   }
 
+  final private boolean jj_3R_13() {
+    if (jj_scan_token(QUOTED_STRING)) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_12() {
+    if (jj_scan_token(FLOAT)) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_11() {
+    if (jj_scan_token(INT)) return true;
+    return false;
+  }
+
+  final private boolean jj_3R_10() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_11()) {
+    jj_scanpos = xsp;
+    if (jj_3R_12()) {
+    jj_scanpos = xsp;
+    if (jj_3R_13()) {
+    jj_scanpos = xsp;
+    if (jj_3R_14()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  final private boolean jj_3R_3() {
+    if (jj_3R_4()) return true;
+    return false;
+  }
+
   final private boolean jj_3R_8() {
     if (jj_scan_token(8)) return true;
     return false;
@@ -250,42 +324,6 @@
     return false;
   }
 
-  final private boolean jj_3R_13() {
-    if (jj_scan_token(QUOTED_STRING)) return true;
-    return false;
-  }
-
-  final private boolean jj_3R_12() {
-    if (jj_scan_token(FLOAT)) return true;
-    return false;
-  }
-
-  final private boolean jj_3R_11() {
-    if (jj_scan_token(INT)) return true;
-    return false;
-  }
-
-  final private boolean jj_3R_10() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_11()) {
-    jj_scanpos = xsp;
-    if (jj_3R_12()) {
-    jj_scanpos = xsp;
-    if (jj_3R_13()) {
-    jj_scanpos = xsp;
-    if (jj_3R_14()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  final private boolean jj_3R_3() {
-    if (jj_3R_4()) return true;
-    return false;
-  }
-
   public ParserTokenManager token_source;
   SimpleCharStream jj_input_stream;
   public Token token, jj_nt;
@@ -293,6 +331,7 @@
   private Token jj_scanpos, jj_lastpos;
   private int jj_la;
   public boolean lookingAhead = false;
+  private boolean jj_semLA;
   private int jj_gen;
   final private int[] jj_la1 = new int[6];
   static private int[] jj_la1_0;

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.jj
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.jj?rev=423723&r1=423722&r2=423723&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.jj (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/Parser.jj Wed Jul 19 19:46:26 2006
@@ -34,6 +34,7 @@
 import org.apache.log4j.Logger;
 import java.io.*; 
 import java.util.*;
+import org.apache.cayenne.wocompat.PlistDataStructureFactory;
 
 /**
  * NeXT/Apple Property List format parser. 
@@ -42,37 +43,66 @@
  * <a href="http://www.reportmill.com/">http://www.reportmill.com/</a></p>
  */
 public class Parser {
-   
     private static Logger logObj = Logger.getLogger(Parser.class);
     
+    private PlistDataStructureFactory factory = new DefaultPlistDataStructureFactory();
+    
     public Parser() {
-        this(System.in);
+        this(System.in, null);
     }
-
-    public Parser(String filename) throws FileNotFoundException {
-        this(new FileInputStream(filename));
+    
+    public Parser(PlistDataStructureFactory factory) {
+        this(System.in, factory);
     }
 
-    public Parser(File f) throws FileNotFoundException {
-        this(new FileInputStream(f));
+    public Parser(String filename, PlistDataStructureFactory factory) throws FileNotFoundException {
+        this(new FileInputStream(filename), factory);
     }
 
+    public Parser(File f, PlistDataStructureFactory factory) throws FileNotFoundException {
+        this(new FileInputStream(f), factory);
+    }
+    
+    public Parser(InputStream in, PlistDataStructureFactory factory) {
+        this(in);
+        
+        if(factory != null) {
+            this.factory = factory;
+        }
+    }
+    
     public Object propertyList() {
         try {
-            return object();
+            return object("");
         }
         catch (ParseException pe) {
            logObj.info("Error parsing plist", pe);
            return null;
         }
     }
-
-public static void main(String args[]) {
-  Parser r = new Parser();
-  Object o = r.propertyList();
-  System.out.println(o);
-  }
-
+    
+    /**
+     * @deprecated since 3.0, use 'object(String)' instead.
+     */
+    public Object object() throws ParseException {
+        return object("");
+    }
+    
+    /**
+     * @deprecated since 3.0, use 'map(String)' instead.
+     */
+    public final java.util.HashMap dictionary()
+                                   throws ParseException {
+            return (java.util.HashMap) map("");                       
+    }
+    
+    /**
+     * @deprecated since 3.0, use 'collection(String)' instead.
+     */
+    public final java.util.ArrayList array()
+                                   throws ParseException {
+            return (java.util.ArrayList) collection("");                       
+    }
 }
 PARSER_END(Parser)
 
@@ -176,14 +206,14 @@
   < QUOTED_STRING: "\"" > { image.setLength(image.length()-1); matchedToken.image = image.toString(); } : DEFAULT
 }
 
-Object object() :
+Object object(String parentKeyPath) :
 {
 	Object node;
 }
 {
-		node=array() { return node; }
+		node=collection(parentKeyPath) { return node; }
 	|   
-		node=dictionary() { return node; }
+		node=map(parentKeyPath) { return node; }
 	|   
 		node=leaf() { return node; }
 }
@@ -197,16 +227,16 @@
 | <STRING> { return token.image; }
 }
 
-HashMap dictionary() : 
+Map map(String parentKeyPath) : 
 { 
-	HashMap h;
+	Map h;
 }
 {
-	"{"  {h = new HashMap(); }
+	"{"  {h = factory.createMap(parentKeyPath); }
 	 (
-		keyValuePair(h)
+		keyValuePair(parentKeyPath, h)
 		(
-			LOOKAHEAD(2) ";" keyValuePair(h)
+			LOOKAHEAD(2) ";" keyValuePair(parentKeyPath, h)
     	)* 
     	
     	// last semicolon is optional
@@ -216,24 +246,24 @@
 	"}" { return h; }
 }
 
-void keyValuePair(Map map) :
+void keyValuePair(String parentKeyPath, Map map) :
 {
 	Object key, val;
 }
 {
-		key = object() 
+		key = object(parentKeyPath) 
 		"=" 
-		val = object() { map.put(key, val); }
+		val = object(parentKeyPath + "." + key) { map.put(key, val); }
 }
 
-ArrayList  array() : 
-{ ArrayList v;
+Collection collection(String parentKeyPath) : 
+{ Collection v;
   Object o;
 }
 {
-   "(" { v = new ArrayList(); } (
-      o=object() { v.add(o); }
-      ("," o=object() { v.add(o); } )*
+   "(" { v = factory.createCollection(parentKeyPath); } (
+      o=object(parentKeyPath) { v.add(o); }
+      ("," o=object(parentKeyPath) { v.add(o); } )*
      )?
    ")" {return v;}
 }

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/ParserTokenManager.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/ParserTokenManager.java?rev=423723&r1=423722&r2=423723&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/ParserTokenManager.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/wocompat/parser/ParserTokenManager.java Wed Jul 19 19:46:26 2006
@@ -18,7 +18,12 @@
  *  under the License.
  ****************************************************************/
 
+
 package org.apache.cayenne.wocompat.parser;
+import org.apache.log4j.Logger;
+import java.io.*;
+import java.util.*;
+import org.apache.cayenne.wocompat.PlistDataStructureFactory;
 
 public class ParserTokenManager implements ParserConstants
 {
@@ -126,16 +131,22 @@
       jjCheckNAdd(jjnextStates[start]);
    } while (start++ != end);
 }
+private final void jjCheckNAddStates(int start)
+{
+   jjCheckNAdd(jjnextStates[start]);
+   jjCheckNAdd(jjnextStates[start + 1]);
+}
 static final long[] jjbitVec0 = {
    0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
 };
 private final int jjMoveNfa_0(int startState, int curPos)
 {
+   int[] nextStates;
    int startsAt = 0;
    jjnewStateCnt = 10;
    int i = 1;
    jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
+   int j, kind = 0x7fffffff;
    for (;;)
    {
       if (++jjround == 0x7fffffff)
@@ -288,6 +299,14 @@
 {
    return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
 }
+private final int jjStartNfaWithStates_2(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_2(state, pos + 1);
+}
 private final int jjMoveStringLiteralDfa0_2()
 {
    switch(curChar)
@@ -348,11 +367,12 @@
 }
 private final int jjMoveNfa_2(int startState, int curPos)
 {
+   int[] nextStates;
    int startsAt = 0;
    jjnewStateCnt = 11;
    int i = 1;
    jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
+   int j, kind = 0x7fffffff;
    for (;;)
    {
       if (++jjround == 0x7fffffff)
@@ -497,11 +517,12 @@
 }
 private final int jjMoveNfa_1(int startState, int curPos)
 {
+   int[] nextStates;
    int startsAt = 0;
    jjnewStateCnt = 2;
    int i = 1;
    jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
+   int j, kind = 0x7fffffff;
    for (;;)
    {
       if (++jjround == 0x7fffffff)
@@ -535,6 +556,7 @@
       }
       else if (curChar < 128)
       {
+         long l = 1L << (curChar & 077);
          MatchLoop: do
          {
             switch(jjstateSet[--i])
@@ -667,6 +689,8 @@
 
 public Token getNextToken() 
 {
+  int kind;
+  Token specialToken = null;
   Token matchedToken;
   int curPos = 0;
 
@@ -841,9 +865,9 @@
          jjimageLen = 0;
         int oct;
         len = image.length();
-        oct = (image.charAt(len-1)-'0') +
-              8 * (image.charAt(len-2)-'0') +
-              64 * (image.charAt(len-3)-'0');
+        oct = ((int)(image.charAt(len-1)-'0')) +
+              8 * ((int)(image.charAt(len-2)-'0')) +
+              64 * ((int)(image.charAt(len-3)-'0'));
         image.setCharAt(len-4, (char)oct);
         image.setLength(len-3);
          break;
@@ -853,10 +877,10 @@
          else
             image.append(new String(input_stream.GetSuffix(jjimageLen)));
          jjimageLen = 0;
-        int c, base=1,hex=0;
+        int dig,c, base=1,hex=0;
         len = image.length();
         for(int i=0; i<4; ++i) {
-          c=image.charAt(len-(i+1));
+          c=(int)image.charAt(len-(i+1));
           if (c<='9') c-='0';
             else if (c<='F') c = (c -'A') + 10;
               else c =(c -'a') + 10;

Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/wocompat/parser/PropertyListParserTst.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/wocompat/parser/PropertyListParserTst.java?rev=423723&r1=423722&r2=423723&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/wocompat/parser/PropertyListParserTst.java (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/wocompat/parser/PropertyListParserTst.java Wed Jul 19 19:46:26 2006
@@ -42,7 +42,7 @@
         list.add("str");
         list.add(new Integer(5));
 
-        Object plist = parser("(str, 5)").object();
+        Object plist = parser("(str, 5)").object("");
         assertTrue(list.equals(plist));
     }
 
@@ -51,7 +51,7 @@
         map.put("key1", "val");
         map.put("key2", new Integer(5));
 
-        Object plist = parser("{key1 = val; key2 = 5}").object();
+        Object plist = parser("{key1 = val; key2 = 5}").object("");
         assertTrue(map.equals(plist));
     }
 
@@ -60,7 +60,7 @@
         list.add("s\"tr");
         list.add(new Integer(5));
 
-        Object plist = parser("(\"s\\\"tr\", 5)").object();
+        Object plist = parser("(\"s\\\"tr\", 5)").object("");
         assertTrue(list.equals(plist));
     }
 
@@ -74,7 +74,7 @@
         list.add(new Integer(5));
         map.put("key3", list);
 
-        assertEquals(map, parser("{key1 = val; key2 = 5; key3 = (str, 5)}").object());
+        assertEquals(map, parser("{key1 = val; key2 = 5; key3 = (str, 5)}").object(""));
     }
 
     public void testStringWithSpaces() throws Exception {
@@ -82,7 +82,7 @@
         list.add("s tr");
         list.add(new Integer(5));
 
-        Object plist = parser("(\"s tr\", 5)").object();
+        Object plist = parser("(\"s tr\", 5)").object("");
         assertTrue(list.equals(plist));
     }
 
@@ -91,7 +91,7 @@
         list.add("s{t)r");
         list.add(new Integer(5));
 
-        assertEquals(list, parser("(\"s{t)r\", 5)").object());
+        assertEquals(list, parser("(\"s{t)r\", 5)").object(""));
     }
 
     public void testStringWithSlashes() throws Exception {
@@ -99,7 +99,7 @@
         list.add("s/t\\r");
         list.add(new Integer(5));
 
-        assertEquals(list, parser("(\"s/t\\\\r\", 5)").object());
+        assertEquals(list, parser("(\"s/t\\\\r\", 5)").object(""));
     }
 
     public void testMapWithLastSemicolon() throws Exception {
@@ -108,55 +108,55 @@
         map.put("key2", new Integer(5));
 
         // last semicolon is optional
-        assertEquals(map, parser("{key1 = val; key2 = 5; }").object());
-        assertEquals(map, parser("{key1 = val; key2 = 5 }").object());
+        assertEquals(map, parser("{key1 = val; key2 = 5; }").object(""));
+        assertEquals(map, parser("{key1 = val; key2 = 5 }").object(""));
     }
 
     public void testEmptyMap() throws Exception {
-        assertEquals(Collections.EMPTY_MAP, parser("{}").object());
+        assertEquals(Collections.EMPTY_MAP, parser("{}").object(""));
     }
 
     public void testEmptyList() throws Exception {
-        assertEquals(Collections.EMPTY_LIST, parser("()").object());
+        assertEquals(Collections.EMPTY_LIST, parser("()").object(""));
     }
 
     public void testOutsideComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("// comment\n ( str)").object());
+        assertEquals(list, parser("// comment\n ( str)").object(""));
     }
 
     public void testInsideComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("(\n // comment\n str )").object());
+        assertEquals(list, parser("(\n // comment\n str )").object(""));
     }
 
     public void testInsideKVComments() throws Exception {
         Map map = Collections.singletonMap("str", new Integer(5));
-        assertEquals(map, parser("{\n str = // comment\n 5; }").object());
+        assertEquals(map, parser("{\n str = // comment\n 5; }").object(""));
     }
 
     public void testTrailingComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("(// comment\n str)").object());
+        assertEquals(list, parser("(// comment\n str)").object(""));
     }
 
     public void testDoubleslashInsideLiteral() throws Exception {
         List list = Collections.singletonList("s//tr");
-        assertEquals(list, parser("( \"s//tr\" )").object());
+        assertEquals(list, parser("( \"s//tr\" )").object(""));
     }
 
     public void testWindowsComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("// comment\r\n ( str)").object());
+        assertEquals(list, parser("// comment\r\n ( str)").object(""));
     }
 
     public void testMacComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("// comment\r ( str)").object());
+        assertEquals(list, parser("// comment\r ( str)").object(""));
     }
 
     public void testUNIXComments() throws Exception {
         List list = Collections.singletonList("str");
-        assertEquals(list, parser("// comment\n ( str)").object());
+        assertEquals(list, parser("// comment\n ( str)").object(""));
     }
 }