Hi All,

As I've stated in earlier e-mail to the list, I've had pretty good luck
with Castor. I recently embarked on changing our current database layout
so that it would better match the object layout/DTD/XSD for our project's
events. So here's the approach I took.

1) wrote an SQL script to create a test database
2) wrote a mapping XML to marshal to/from the database
3) wrote an XSD so that the Castor SourceGenerator could provide the code.

The SourceGenerator provides methods for "collections" in the form of

        void setXXX( YYY[] array );
        YYY[] getXXX( );

Well I noticed that the mapping.dtd for the "field" element allows the
attribute "collection" that may be one of:

        array
        vector
        hashtable
        collection
        set
        map

I chose to use the "array" setting since that matched what was
generated by the SourceGenerator. I figured this was the ultimate in being
able to manage changes. In effect I would have castor generate my 
source classes, XML, and SQL.... This would have really cut down on my
work if it were not for one simple fact: Arrays are not implemented 
yet!

After my initial disallusionment passed I hunkered down and attempted to
write the missing code. I seemed to be having a fair bit of success, except
that I'm stuck and I don't know how to proceed. I could really use some
help from those who understand the source better than I.

I've attached the context diff of my changes to the latest CVS source tree
for castor (see castor.patch). These can be applied using:

        cvs co castor
        cd castor
        patch -p1 < ../castor.patch

Once the changes are applied, build and then unpack the compressed tar
into another directory.

        mkdir test
        cd test
        tar xzvf ../testset.tgz
        java org.exolab.castor.builder.SourceGenerator \
                -i schema/mapping/event.xsd \
                -package org.opennms.netmgt.xml.event \
                -types j2 \
                -dest srcgen
        mkdir work/classes
        cd srcgen
        find org -name \*.java -print > listing
        javac -g -d ../work/classes @listing
        cd ..
        cp schema/mapping/event.xml \
                work/classes/org/opennms/netmgt/xml/event
        javac -g -d work/classes schema/mapping/Test.java

At this point all you need is a database.xml where the test program
can locate it, and a database of course. I'm using PostgreSQL 7.1
and have used the 'schema/mapping/event.sql' to create the tables.

I get the following results on the first run:
----------------------------------

org.exolab.castor.jdo.PersistenceException: Nested error: No class found for 
org.opennms.netmgt.xml.event.Parameter.
No class found for org.opennms.netmgt.xml.event.Parameter.
        at org.postgresql.Connection.putObject(Connection.java:812)
        at org.postgresql.jdbc2.PreparedStatement.setObject(PreparedStatement.java:596)
        at org.exolab.castor.jdo.engine.SQLEngine.load(SQLEngine.java:999)
        at org.exolab.castor.persist.ClassMolder.load(ClassMolder.java:646)
        at org.exolab.castor.persist.LockEngine.load(LockEngine.java:361)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:545)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:479)
        at org.exolab.castor.persist.ClassMolder.load(ClassMolder.java:742)
        at org.exolab.castor.persist.LockEngine.load(LockEngine.java:361)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:545)
        at org.exolab.castor.persist.QueryResults.fetch(QueryResults.java:229)
        at 
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:573)
        at 
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:556)
        at org.opennms.netmgt.db.Test.run(Test.java:132)
        at org.opennms.netmgt.db.Test.main(Test.java:35)

----------------------------------


On the second run I get:
----------------------------------

Begin transaction
<?xml version="1.0"?>
<event id="1">
    <create-time>2001-07-31 10:29:00 </create-time>
    <uei>http://uei.opennms.org/event/bogus</uei>
    <source>fake.opennms.org</source>
    <time>2001-07-31 10:28:59 </time>
    <snmp id="1">
        <enterprise-id>.1.3.6.1.4.3.1.3.2.2.1</enterprise-id>
        <version>SNMPv1</version>
        <generic>6</generic>
        <specific>32</specific>
    </snmp>
    <parameter event-id="1" name="retries" type="string" encoding="text" 
id="1">3</parameter>
    <parameter event-id="1" name="timeout" type="string" encoding="text" 
id="2">2000</parameter>
</event>
<event id="1">
    <create-time>2001-07-31 10:29:00 </create-time>
    <uei>http://uei.opennms.org/event/bogus</uei>
    <source>fake.opennms.org</source>
    <time>2001-07-31 10:28:59 </time>
    <snmp id="1">
        <enterprise-id>.1.3.6.1.4.3.1.3.2.2.1</enterprise-id>
        <version>SNMPv1</version>
        <generic>6</generic>
        <specific>32</specific>
    </snmp>
    <parameter event-id="1" name="retries" type="string" encoding="text" 
id="1">3</parameter>
    <parameter event-id="1" name="timeout" type="string" encoding="text" 
id="2">2000</parameter>
</event>
org.exolab.castor.jdo.PersistenceException: Nested error: No class found for 
org.opennms.netmgt.xml.event.Parameter.
No class found for org.opennms.netmgt.xml.event.Parameter.
        at org.postgresql.Connection.putObject(Connection.java:812)
        at org.postgresql.jdbc2.PreparedStatement.setObject(PreparedStatement.java:596)
        at org.exolab.castor.jdo.engine.SQLEngine.load(SQLEngine.java:999)
        at org.exolab.castor.persist.ClassMolder.load(ClassMolder.java:646)
        at org.exolab.castor.persist.LockEngine.load(LockEngine.java:361)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:545)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:479)
        at org.exolab.castor.persist.ClassMolder.load(ClassMolder.java:742)
        at org.exolab.castor.persist.LockEngine.load(LockEngine.java:361)
        at 
org.exolab.castor.persist.TransactionContext.load(TransactionContext.java:545)
        at org.exolab.castor.persist.QueryResults.fetch(QueryResults.java:229)
        at 
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:573)
        at 
org.exolab.castor.jdo.engine.OQLQueryImpl$OQLEnumeration.hasMore(OQLQueryImpl.java:556)
        at org.opennms.netmgt.db.Test.run(Test.java:132)
        at org.opennms.netmgt.db.Test.main(Test.java:35)

----------------------------------

So it does appear to be working to a limited degree. Any
help would be greatly appreciated.

Weave

diff -ur --exclude=CVS 
castor/src/main/org/exolab/castor/builder/castorbuilder.properties 
castor.new/src/main/org/exolab/castor/builder/castorbuilder.properties
--- castor/src/main/org/exolab/castor/builder/castorbuilder.properties  Wed Jul 11 
07:12:09 2001
+++ castor.new/src/main/org/exolab/castor/builder/castorbuilder.properties      Tue 
+Jul 24 05:06:09 2001
@@ -8,7 +8,7 @@
 # when enabled. This will change in the future when we introduce
 # fine grained control over each class and it's properties.
 #
-#org.exolab.castor.builder.boundproperties=true
+org.exolab.castor.builder.boundproperties=true
 
 # Java class mapping of <xsd:element>'s and <xsd:complexType>'s 
 #
@@ -22,13 +22,13 @@
 # XML namespace mapping to Java packages
 #
 #org.exolab.castor.builder.nspackages=\
-  http://www.xyz.com/schemas/project=com.xyz.schemas.project,\
-  http://www.xyz.com/schemas/person=com.xyz.schemas.person
+#  http://www.xyz.com/schemas/project=com.xyz.schemas.project,\
+#  http://www.xyz.com/schemas/person=com.xyz.schemas.person
 
 # Set to true if you want to generate the equals method
 # for each generated class
 # false by default
-#org.exolab.castor.builder.equalsmethod=true
+org.exolab.castor.builder.equalsmethod=true
 
 # Set to true if you want to use Object Wrappers instead
 # of primitives (e.g Float instead of float).
diff -ur --exclude=CVS castor/src/main/org/exolab/castor/castor.properties 
castor.new/src/main/org/exolab/castor/castor.properties
--- castor/src/main/org/exolab/castor/castor.properties Wed Jan 10 21:24:35 2001
+++ castor.new/src/main/org/exolab/castor/castor.properties     Mon Jul 30 16:44:31 
+2001
@@ -62,7 +62,7 @@
 
 # True if all documents should be indented on output by default
 #
-#org.exolab.castor.indent=true
+org.exolab.castor.indent=true
 
 
 # True if xml documents should be validated by the SAX Parser
diff -ur --exclude=CVS castor/src/main/org/exolab/castor/persist/ClassMolder.java 
castor.new/src/main/org/exolab/castor/persist/ClassMolder.java
--- castor/src/main/org/exolab/castor/persist/ClassMolder.java  Mon Jul 23 19:13:06 
2001
+++ castor.new/src/main/org/exolab/castor/persist/ClassMolder.java      Wed Aug  1 
+13:55:28 2001
@@ -46,7 +46,7 @@
 
 package org.exolab.castor.persist;
 
-
+import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -1555,7 +1555,7 @@
         if ( collection == null )
             return new ArrayList(0);
 
-        if ( collection instanceof Map ) {
+        else if ( collection instanceof Map ) {
             if ( orgIds == null || orgIds.size() == 0 ) {
                 if ( collection == null )
                     return new ArrayList(0);
@@ -1574,7 +1574,7 @@
             return added;
         }
 
-        if ( collection instanceof Collection ) {
+        else if ( collection instanceof Collection ) {
             if ( orgIds == null || orgIds.size() == 0 ) {
                 if ( collection == null )
                     return new ArrayList(0);
@@ -1597,6 +1597,34 @@
             return added;
         }
 
+        else if ( collection instanceof Object[] ) {
+            if ( orgIds == null || orgIds.size() == 0 ) {
+                if ( collection == null )
+                    return new ArrayList(0);
+                else
+               {
+                       Object[] sx  = (Object[]) collection;
+                       Collection c = new ArrayList(sx.length);
+                       for(int x = 0; x < sx.length; x++)
+                               c.add(sx[x]);
+                       return c;
+               }
+            }
+
+            if ( collection == null )
+                return new ArrayList(0);
+
+            Object[] newValues = (Object[]) collection;
+            ArrayList added = new ArrayList( newValues.length );
+           for(int x = 0; x < newValues.length; x++) {
+                Object newValue = newValues[x];
+                Object newId = ch.getIdentity( tx, newValue );
+                if ( newId == null || !orgIds.contains( newId ) )
+                    added.add( newValue );
+            }
+            return added;
+        }
+
         throw new IllegalArgumentException( "Collection type 
"+collection.getClass().getName()+" is not supported!" );
     }
 
@@ -1612,8 +1640,7 @@
             else
                 return orgIds;
         }
-
-        if ( collection instanceof Map ) {
+        else if ( collection instanceof Map ) {
             if ( orgIds == null || orgIds.size() == 0 )
                 return new ArrayList(0);
 
@@ -1627,8 +1654,7 @@
             }
             return removed;
         }
-
-        if ( collection instanceof Collection ) {
+        else if ( collection instanceof Collection ) {
             if ( orgIds == null || orgIds.size() == 0 )
                 return new ArrayList(0);
 
@@ -1637,21 +1663,45 @@
             ArrayList removed = new ArrayList(0);
 
             // make a new map of key and value of the new collection
-            HashMap newMap = new HashMap();
+            HashSet newSet = new HashSet();
             Iterator newColItor = newCol.iterator();
             while ( newColItor.hasNext() ) {
                 Object newObject = newColItor.next();
                 Object newId = ch.getIdentity( tx, newObject );
                 if ( newId != null )
-                    newMap.put( newId, newObject );
+                    newSet.add( newId );
             }
             while ( orgItor.hasNext() ) {
                 Object id = orgItor.next();
-                if ( !newMap.containsKey( id ) )
+                if ( !newSet.contains( id ) )
                     removed.add( id );
             }
             return removed;
         }
+       else if( collection instanceof Object[] ) {
+               if( orgIds == null || orgIds.size() == 0 )
+                       return new ArrayList(0);
+
+               Object[] newCol = (Object[]) collection;
+               int newColNdx = 0;
+               Iterator orgItor = orgIds.iterator();
+               ArrayList removed = new ArrayList(0);
+
+               // make a new map of key and value of the new collection
+               HashSet newSet = new HashSet();
+               while(newColNdx < newCol.length) {
+                       Object newObject = newCol[newColNdx++];
+                       Object newId = ch.getIdentity( tx, newObject );
+                       if ( newId != null )
+                               newSet.add( newId );
+               }
+               while ( orgItor.hasNext() ) {
+                       Object id = orgItor.next();
+                       if ( !newSet.contains( id ) )
+                               removed.add( id );
+               }
+               return removed;
+       }
 
         throw new IllegalArgumentException( "Collection type 
"+collection.getClass().getName()+" is not supported!" );
     }
@@ -2870,6 +2920,20 @@
             return ((Collection) o).iterator();
         } else if ( o instanceof Map ) {
             return ((Map) o).values().iterator();
+       } else if ( o instanceof Object[] ) {
+           final Object[] _inner_src = (Object[])o;
+           return new Iterator() {
+                   private int _x = 0;
+                   public boolean hasNext() {
+                       return (_x < _inner_src.length);
+                   }
+                   public Object next() {
+                       return _inner_src[_x++];
+                   }
+                   public void remove() {
+                       throw new UnsupportedOperationException("array removal not 
+supported!");
+                   }
+               };
         } else {
             throw new IllegalArgumentException();
         }
@@ -2905,7 +2969,14 @@
                 idList.add( itor.next() );
             }
             return idList;
-        } else {
+        } else if ( col instanceof Object[] ) {
+               ArrayList idList = new ArrayList();
+               Object[] src = (Object[])col;
+               for(int x = 0; x < src.length; x++)
+                       idList.add( src[x] );
+               return idList;
+       }
+       else {
             throw new IllegalArgumentException("A Collection or Map is expected!");
         }
     }
@@ -2952,6 +3023,18 @@
             return new MapProxy( fm, object, cl, new HashMap() );
         } else if ( cls == Map.class ) {
             return new MapProxy( fm, object, cl, new HashMap() );
+       } else if ( cls == Object[].class ) {
+           try {
+               Class ref;
+               if( cl == null )
+                  ref = 
+ClassLoader.getSystemClassLoader().loadClass(fm.getTypeName());
+               else
+                  ref = cl.loadClass(fm.getTypeName());
+               return new ArrayProxy( fm, object, cl, (Object[]) 
+Array.newInstance(ref, 0) );
+           }
+           catch(ClassNotFoundException cnfE) {
+               throw new IllegalArgumentException("Collection Proxy could not load 
+class type " + fm.getTypeName());
+           }
         } else {
             throw new IllegalArgumentException("Collection Proxy doesn't exist for it 
type");
         }
@@ -3005,6 +3088,49 @@
                 _fm.setValue( _object, _map, _cl );
         }
 
+    }
+
+    private static class ArrayProxy extends CollectionProxy {
+        private Object[] _array;
+        private FieldMolder _fm;
+        private Object _object;
+        private ClassLoader _cl;
+        private ArrayProxy( FieldMolder fm, Object object, ClassLoader cl, Object[] 
+array ) {
+            _cl = cl;
+            _fm = fm;
+            _array = array;
+            _object = object;
+        }
+        Object getCollection() {
+            return _array;
+        }
+        void add( Object key, Object value ) {
+            if ( !_fm.isAddable() )
+           {
+                   if(_array != null)
+                   {
+                       Object[] dst = (Object[]) Array.newInstance(value.getClass(), 
+_array.length+1);
+                       System.arraycopy(_array,
+                                        0,
+                                        dst,
+                                        0,
+                                        _array.length);
+                       dst[_array.length] = value;
+                       _array = dst;
+                   }
+                   else
+                   {
+                           _array = (Object[]) Array.newInstance(value.getClass(), 1);
+                           _array[0] = value;
+                   }
+           }
+            else
+                _fm.addValue( _object, value, _cl );
+        }
+        void close() {
+            if ( !_fm.isAddable() )
+                _fm.setValue( _object, _array, _cl );
+        }
     }
 }
 
diff -ur --exclude=CVS castor/src/main/org/exolab/castor/persist/FieldMolder.java 
castor.new/src/main/org/exolab/castor/persist/FieldMolder.java
--- castor/src/main/org/exolab/castor/persist/FieldMolder.java  Thu Jul 26 14:35:33 
2001
+++ castor.new/src/main/org/exolab/castor/persist/FieldMolder.java      Wed Aug  1 
+11:50:34 2001
@@ -123,6 +123,11 @@
         return "FieldMolder of "+_eMold.getName()+".set"+_fieldName+"("+_fType+" 
"+_fieldName+")";
     }
 
+    public String getTypeName()
+    {
+           return _fType;
+    }
+
     /*
     void setRelationDescriptor( RelationDescriptor rd ) throws MappingException {
         _loader = new SQLRelationLoader( rd, _eMold.getName() );

testset.tgz

Reply via email to