Hello,

this is a patch for jBoss (cvs-snapshot from 2001-01-30) that enables
nested fields like this:

[...]
      <cmp-field>
                                <field-name>data.categoryPK</field-name>
      </cmp-field>
[...]

With this patch, you no longer have to follow the advice on
http://www.jboss.org/newsite/manual/developing.html#entity
(the EMailAddress example).

Unfortunately, there is no fixed jBoss version I can patch against. If
you are interested, I can send you the original snapshot and the patch
by mail.

Nevertheless, I have included the output from patch so you can get the
idea.

-- 
        /// Dirk.

diff -Naur orig/main/org/jboss/ejb/plugins/CMPPersistenceManager.java 
patched/main/org/jboss/ejb/plugins/CMPPersistenceManager.java
--- orig/main/org/jboss/ejb/plugins/CMPPersistenceManager.java  Fri Jan 26 21:31:24 
2001
+++ patched/main/org/jboss/ejb/plugins/CMPPersistenceManager.java       Fri Feb 09 
+10:48:39 2001
@@ -33,6 +33,8 @@
 import org.jboss.ejb.EntityPersistenceStore;
 import org.jboss.metadata.EntityMetaData;
 
+import org.jboss.logging.Logger;
+
 /**
 *   The CMP Persistence Manager implements the semantics of the CMP
 *  EJB 1.1 call back specification.
@@ -146,7 +148,7 @@
                                        cmpFieldType = cmpField.getType();
                                        // find the type of the field and reset it
                                        // to the default value
-                                       if (cmpFieldType.equals(boolean.class))  {
+                                       if (    cmpFieldType.equals(boolean.class))  {
                                                cmpField.setBoolean(instance,false);
                                        } else if (cmpFieldType.equals(byte.class))  {
                                                cmpField.setByte(instance,(byte)0);
diff -Naur orig/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java 
patched/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java
--- orig/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java  Thu Dec 07 16:44:36 
2000
+++ patched/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCCommand.java       Thu Feb 08 
+19:07:30 2001
@@ -103,7 +103,7 @@
    /**
     * Gives compile-time control of tracing.
     */
-   public static boolean debug = false;
+   public static boolean debug = true;
 
    // Constructors --------------------------------------------------
 
@@ -355,6 +355,25 @@
    }
 
 
+       /**
+        * DZ
+        * Wrapper around getResultObject(ResultSet rs, int idx, Class destination).
+        */
+       protected Object getResultObject(ResultSet rs, int idx, CMPFieldMetaData 
+cmpField)
+               throws SQLException {
+               if (!cmpField.isComposite()) {
+                       // do it as before
+                       return getResultObject(rs, idx, cmpField.getField().getType());
+               }
+
+               // deal with composite object
+               log.warning("Using Inprise feature.");
+
+               // Assuming no one will ever use BLOPS in composite objects.
+               // TODO Should be tested for BLOPability
+               return rs.getObject(idx);
+       }
+
    /**
     * Used for all retrieval of results from <code>ResultSet</code>s.
     * Implements tracing, and allows some tweaking of returned types.
@@ -578,8 +597,10 @@
    protected Object getCMPFieldValue(Object instance, CMPFieldMetaData fieldMetaData)
       throws IllegalAccessException
    {
-      Field field = fieldMetaData.getField();
-      return field.get(instance);
+                // DZ
+                //Field field = fieldMetaData.getField();
+                //return field.get(instance);
+                return fieldMetaData.getValue(instance);
    }
 
    protected void setCMPFieldValue(Object instance,
@@ -587,8 +608,16 @@
                                    Object value)
       throws IllegalAccessException
    {
-      Field field = fieldMetaData.getField();
-      field.set(instance, value);
+                // DZ
+                if (fieldMetaData.isComposite()) {
+                        // we have a composite field
+                        fieldMetaData.set(instance, value);
+                }
+                else {
+                        // the usual way
+                        Field field = fieldMetaData.getField();
+                        field.set(instance, value);
+                }
    }
 
    protected Object getPkFieldValue(Object pk, PkFieldMetaData pkFieldMetaData)
diff -Naur orig/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCLoadEntityCommand.java 
patched/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCLoadEntityCommand.java
--- orig/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCLoadEntityCommand.java        Thu 
Dec 07 16:44:38 2000
+++ patched/main/org/jboss/ejb/plugins/jaws/jdbc/JDBCLoadEntityCommand.java     Thu 
+Feb 08 16:28:23 2001
@@ -111,7 +111,9 @@
          
          setCMPFieldValue(ctx.getInstance(), 
                           cmpField, 
-                          getResultObject(rs, idx++, cmpField.getField().getType()));
+                                                                                      
+                 // DZ
+                          //getResultObject(rs, idx++, 
+cmpField.getField().getType()));
+                          getResultObject(rs, idx++, cmpField));
       }
 
       // Store state to be able to do tuned updates
diff -Naur orig/main/org/jboss/ejb/plugins/jaws/metadata/CMPFieldMetaData.java 
patched/main/org/jboss/ejb/plugins/jaws/metadata/CMPFieldMetaData.java
--- orig/main/org/jboss/ejb/plugins/jaws/metadata/CMPFieldMetaData.java Thu Dec 07 
16:44:40 2000
+++ patched/main/org/jboss/ejb/plugins/jaws/metadata/CMPFieldMetaData.java      Thu 
+Feb 08 19:25:41 2001
@@ -11,6 +11,9 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
+// DZ
+import java.util.*;
+
 import org.w3c.dom.Element;
 
 import org.jboss.ejb.DeploymentException;
@@ -19,6 +22,9 @@
 import org.jboss.metadata.MetaData;
 import org.jboss.metadata.EjbRefMetaData;
 
+// DZ
+import org.jboss.logging.Log;
+import org.jboss.logging.Logger;
 
 
 /**
@@ -55,6 +61,25 @@
        private String columnName;
        
        private boolean isAPrimaryKeyField;
+
+       /**
+        * DZ
+        * We need this for the Inprise Hack.
+        */
+       private String ejbClassName;
+       
+       
+       /**
+        * DZ
+        * We need this for the Inprise Hack.
+        */
+       private Class ejbClass;
+
+       /**
+        * DZ
+        * Is set for fields like "data.categoryPK".
+        */
+       private boolean isComposite;
        
        
        // Static --------------------------------------------------------
@@ -64,18 +89,25 @@
                this.name = name;
                this.jawsEntity = jawsEntity;
                
-               String ejbClassName = jawsEntity.getEntity().getEjbClass();
+               // DZ
+               ejbClassName = jawsEntity.getEntity().getEjbClass();
+
                try {
-                       Class ejbClass = 
jawsEntity.getJawsApplication().getClassLoader().loadClass(ejbClassName);
-                   field = ejbClass.getField(name);
+                       ejbClass = 
+jawsEntity.getJawsApplication().getClassLoader().loadClass(ejbClassName);
+                       field = ejbClass.getField(name);
                } catch (ClassNotFoundException e) {
                        throw new DeploymentException("ejb class not found: " + 
ejbClassName);
-               } catch (NoSuchFieldException e) {
-                       throw new DeploymentException("cmp-field " + name + " is not a 
field in ejb class " + ejbClassName);
+               }
+               catch (NoSuchFieldException e) {
+                               //throw new DeploymentException("cmp-field " + name + 
+" is not a field in ejb class " + ejbClassName);
+                               Log.getLog().warning("Warning: You rely on an Inprise 
+Application Server feature with " +
+                                                                                      
+                          "field " + name + " in " + ejbClassName);
+                               checkField();
                }
                
                // default, may be overridden by importXml
-               columnName = name;
+               // DZ
+               columnName = getLastComponent(name);
                
                // cannot set defaults for jdbctype/sqltype, type mappings are not 
loaded yet.
        }
@@ -95,6 +127,147 @@
                return jdbcType;
        }
        
+       /**
+        * DZ
+        * Returns the last component of a composite fieldName. E.g., for 
+"data.categoryPK" it
+        * will return "categoryPK".
+        */
+       public static String getLastComponent(String name) {
+               String fieldName = name;
+               StringTokenizer st = new StringTokenizer(name, ".");
+               while(st.hasMoreTokens()) {
+                       fieldName = st.nextToken();
+               }
+               return fieldName;
+       }
+
+       /**
+        * DZ
+        * Detects the actual field of a composite field and sets field accordingly.
+        */
+       private void checkField()       {
+               Field tmpField = null;
+               Class tmpClass = ejbClass;
+               String fieldName = null;
+               StringTokenizer st = new StringTokenizer(name, ".");
+
+               if (st.countTokens() > 1) {
+                       isComposite = true;
+               }
+
+               while(st.hasMoreTokens()) {
+                       fieldName = st.nextToken();
+                       try {
+                               tmpField = tmpClass.getField(fieldName);
+                               tmpClass = tmpField.getType();
+                       }
+                       catch (NoSuchFieldException e) {
+                               Log.getLog().warning("!!! Deployment Failure !!!");
+                       }
+               }
+               field = tmpField;
+       }
+
+       /**
+        * DZ
+        * We don't rely on the field for getting the type since we support nested 
+field
+        * like 'data.categoryPK'.
+        */
+       public Class getFieldType()     {
+               if (field != null) {
+                       // The default case as it always was :)
+                       return field.getType();
+               }
+                               
+               // We obviously have a nested field (or an erroneous one)
+               Field tmpField = null;
+               Class tmpClass = ejbClass;
+               String fieldName = null;
+               StringTokenizer st = new StringTokenizer(name, ".");
+               while(st.hasMoreTokens()) {
+                       fieldName = st.nextToken();
+                       try {
+                               tmpField = tmpClass.getField(fieldName);
+                               tmpClass = tmpField.getType();
+                       }
+                       catch (NoSuchFieldException e) {
+                               Log.getLog().warning("!!! Deployment Failure !!!");
+                       }
+               }
+               return tmpField.getType();
+       }
+
+       /**
+        * DZ
+        * Is used mainly for composite fields. Sets the value of a composite field.
+        */
+       public void set(Object instance, Object value) {
+               Field tmpField = null;
+               String fieldName = null;
+               Object currentObject = instance;
+               Object oldObject;
+               StringTokenizer st = new StringTokenizer(name, ".");
+
+               try {
+                       for (int i = 0; i < st.countTokens() - 1; ++i) {
+                               st.hasMoreTokens();
+                               fieldName = st.nextToken();
+                               tmpField = 
+currentObject.getClass().getField(fieldName);
+                               oldObject = currentObject;
+                               currentObject = tmpField.get(currentObject);
+                               // On our path, we have to instantiate every 
+intermediate object
+                               if (currentObject == null) {
+                                       currentObject = 
+tmpField.getType().newInstance();
+                                       tmpField.set(oldObject, currentObject);
+                               }
+                       }
+                       Field dataField = 
+currentObject.getClass().getField(getLastComponent(name));
+                       dataField.set(currentObject, value);
+               }
+               catch (NoSuchFieldException e) {
+                       Log.getLog().warning("!!! Deployment Failure !!!");
+               }
+               catch (IllegalAccessException e) {
+                       Log.getLog().warning("!!! Deployment Failure !!!");
+               }
+               catch (InstantiationException e) {
+                       Log.getLog().warning("could not instantiate " + tmpField);
+               }
+       }
+
+       /**
+        * DZ
+        * Returns the value of this field.
+        */
+       public Object getValue(Object instance) {
+               String fieldName;
+               Object currentObject = instance;
+               Field currentField;
+               //Object currentValue = null;
+
+               try {
+                       if (!isComposite()) {
+                               return getField().get(instance);
+                       }
+                       else {
+                               StringTokenizer st = new StringTokenizer(name, ".");
+                               while(st.hasMoreTokens()) {
+                                       fieldName = st.nextToken();
+                                       currentField = 
+currentObject.getClass().getField(fieldName);
+                                       currentObject = 
+currentField.get(currentObject);
+                               }
+                               return currentObject;
+                       }
+               }
+               catch (IllegalAccessException e) {
+                       Log.getLog().warning("!!! CMPFieldMetaData.getValue() ERROR 
+!!! " + e);
+               }
+               catch (NoSuchFieldException e) {
+                       Log.getLog().warning("!!! CMPFieldMetaData.getValue() ERROR 
+!!! " + e);
+               }
+               return null;
+       }
+
        public String getSQLType() { 
                if (sqlType == null) {
                        // set the default
@@ -112,7 +285,15 @@
        public JawsEntityMetaData getJawsEntity() { return jawsEntity; }
                
        
-       // XmlLoadable implementation ------------------------------------
+       // DZ
+       public boolean isComposite() {
+               return isComposite;
+       }
+       public void isComposite(boolean v) {
+               this.isComposite = v;
+       }
+
+               // XmlLoadable implementation ------------------------------------
        public void importXml(Element element) throws DeploymentException {
                
                // column name


Reply via email to