openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jrba...@apache.org
Subject svn commit: r1241207 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/conf/ openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ openjpa-kernel/src/main/java/org/apache/openjpa/util/ openjpa-persistence-jdbc/src/main/ant/ openjp...
Date Mon, 06 Feb 2012 22:03:03 GMT
Author: jrbauer
Date: Mon Feb  6 22:03:02 2012
New Revision: 1241207

URL: http://svn.apache.org/viewvc?rev=1241207&view=rev
Log:
OPENJPA-2120 Add option for optimizing copy operations for qualifying id classes.

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
  (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
  (with props)
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
    openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
Mon Feb  6 22:03:02 2012
@@ -1918,5 +1918,37 @@ public interface OpenJPAConfiguration
       */
      public void setPostLoadOnMerge(Boolean postLoadOnMerge);
     
+     /**
+      * Whether to attempt to optimize id class copy operations during the
+      * enhancement process.  Optimization is only applicable for simple id classes
+      * that have a constructor with the proper construction parameters and
+      * direct assignments to fields within the id class during construction. 
+      * If the optimization cannot occur, the enhancer will fallback to the 
+      * noraml behavior.
+      * @since 2.2.0
+      */
+     public boolean getOptimizeIdCopy();
+     
+     /**
+      * Whether to attempt to optimize id class copy operations during the
+      * enhancement process.  Optimization is only applicable for simple id classes
+      * that have a constructor with the proper construction parameters and
+      * direct assignments to fields within the id class during construction. 
+      * If the optimization cannot occur, the enhancer will fallback to the 
+      * normal behavior.
+      * @since 2.2.0
+      */
+     public void setOptimizeIdCopy(boolean optimizeIds);
+
+     /**
+      * Whether to attempt to optimize id class copy operations during the
+      * enhancement process.  Optimization is only applicable for simple id classes
+      * that have a constructor with the proper construction parameters and
+      * direct assignments to fields within the id class during construction. 
+      * If the optimization cannot occur, the enhancer will fallback to the 
+      * normal behavior.
+      * @since 2.2.0
+      */
+      public void setOptimizeIdCopy(Boolean optimizeIds);
 }
 

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
Mon Feb  6 22:03:02 2012
@@ -177,6 +177,7 @@ public class OpenJPAConfigurationImpl
     public ObjectValue instrumentationManager;
     public PluginListValue instrumentationProviders;
     public BooleanValue postLoadOnMerge;
+    public BooleanValue optimizeIdCopy;
     
     // custom values
     public BrokerFactoryValue brokerFactoryPlugin;
@@ -402,6 +403,10 @@ public class OpenJPAConfigurationImpl
         postLoadOnMerge.setDefault("false");
         postLoadOnMerge.set(false);
 
+        optimizeIdCopy = addBoolean("OptimizeIdCopy");
+        optimizeIdCopy.setDefault("false");
+        optimizeIdCopy.set(false);
+        
         autoClear = addInt("AutoClear");
         aliases =
             new String[] { "datastore",
@@ -1856,5 +1861,18 @@ public class OpenJPAConfigurationImpl
             setPostLoadOnMerge(postLoadOnMerge.booleanValue());
     }
 
+    public boolean getOptimizeIdCopy() {
+        return optimizeIdCopy.get();
+    }
+    
+    public void setOptimizeIdCopy(boolean optimizeId) {
+        optimizeIdCopy.set(optimizeId);
+    }
+
+    public void setOptimizeIdCopy(Boolean optimizeId) {
+        if (optimizeId != null) {
+            setOptimizeIdCopy(optimizeId.booleanValue());
+        }
+    }
 }
 

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
Mon Feb  6 22:03:02 2012
@@ -69,6 +69,7 @@ import org.apache.openjpa.meta.FieldMeta
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.MetaDataRepository;
 import org.apache.openjpa.meta.ValueStrategies;
+import org.apache.openjpa.util.ApplicationIds;
 import org.apache.openjpa.util.GeneralException;
 import org.apache.openjpa.util.InternalException;
 import org.apache.openjpa.util.BigDecimalId;
@@ -102,6 +103,7 @@ import serp.bytecode.LoadInstruction;
 import serp.bytecode.LookupSwitchInstruction;
 import serp.bytecode.MethodInstruction;
 import serp.bytecode.Project;
+import serp.bytecode.PutFieldInstruction;
 import serp.bytecode.TableSwitchInstruction;
 import serp.bytecode.ClassInstruction;
 import serp.util.Strings;
@@ -212,6 +214,8 @@ public class PCEnhancer { 
     private boolean _isAlreadySubclassed = false;
     private boolean _bcsConfigured = false;
 
+    private boolean _optimizeIdCopy = false; // whether to attempt optimizing id copy
+    
     /**
      * Constructor. Supply configuration and type to enhance. This will look
      * up the metadata for <code>type</code> from <code>conf</code>'s
@@ -280,6 +284,8 @@ public class PCEnhancer { 
         } else
             _repos = repos;
         _meta = _repos.getMetaData(type.getType(), loader, false);
+        
+        configureOptimizeIdCopy();
     }
 
     /**
@@ -2010,11 +2016,52 @@ public class PCEnhancer { 
         // id.<field> = pc.<field>;
         FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
             : _meta.getDeclaredFields();
-        Class type;
+        Class<?> type; 
         String name;
         Field field;
         Method setter;
         boolean reflect;
+        // If optimizeIdCopy is enabled and not a field manager method, try to
+        // optimize the copyTo by using a public constructor instead of reflection
+        if (_optimizeIdCopy && !fieldManager) {
+            ArrayList<Integer> pkfields = optimizeIdCopy(oidType, fmds);
+            if (pkfields != null) {
+                // search for a constructor on the IdClass that can be used
+                // to construct the IdClass
+                int parmOrder[] = getIdClassConstructorParmOrder(oidType, pkfields, fmds);
+                if (parmOrder != null) {
+                    // found a matching constructor.  parm array is constructor parm order
+                    code.anew().setType(oidType);
+                    code.dup();
+                    // build the parm list in order
+                    Class<?>[] clsArgs = new Class<?>[parmOrder.length];
+                    for (int i = 0; i < clsArgs.length; i++) {
+                        int parmIndex = parmOrder[i];
+                        clsArgs[i] = fmds[parmIndex].getObjectIdFieldType();
+                        loadManagedInstance(code, false);
+                        addGetManagedValueCode(code, fmds[parmIndex]);
+                    }
+                    // invoke the public constructor to create a new local id
+                    code.invokespecial().setMethod(oidType, "<init>", void.class, clsArgs);
+                    int ret = code.getNextLocalsIndex();
+                    code.astore().setLocal(ret);
+
+                    // swap out the app id with the new one
+                    code.aload().setLocal(1);
+                    code.checkcast().setType(ObjectId.class);
+                    code.aload().setLocal(ret);
+                    code.invokestatic().setMethod(ApplicationIds.class, 
+                            "setAppId", void.class, new Class[] { ObjectId.class,
+                            Object.class });
+                    code.vreturn();
+
+                    code.calculateMaxStack();
+                    code.calculateMaxLocals();
+                    return;
+                }
+            }
+        }
+        
         for (int i = 0; i < fmds.length; i++) {
             if (!fmds[i].isPrimaryKey())
                 continue;
@@ -2428,17 +2475,28 @@ public class PCEnhancer { 
                     if (Modifier.isPublic(field.getModifiers()))
                         code.getfield().setField(field);
                     else {
-                        // Reflection.getXXX(oid, Reflection.findField(...));
-                        code.classconstant().setClass(oidType);
-                        code.constant().setValue(name);
-                        code.constant().setValue(true);
-                        code.invokestatic().setMethod(Reflection.class,
-                            "findField", Field.class, new Class[] { 
-                            Class.class, String.class, boolean.class });
-                        code.invokestatic().setMethod
-                            (getReflectionGetterMethod(type, Field.class));
-                        if (!type.isPrimitive() && type != Object.class)
-                            code.checkcast().setType(type);
+                        boolean usedFastOid = false;
+                        if (_optimizeIdCopy) {
+                            // If fastOids, ignore access type and try to use a public getter
+                            getter = Reflection.findGetter(oidType, name, false);
+                            if (getter != null && Modifier.isPublic(getter.getModifiers()))
{
+                                usedFastOid = true;
+                                code.invokevirtual().setMethod(getter);
+                            }
+                        }
+                        if (!usedFastOid) {
+                            // Reflection.getXXX(oid, Reflection.findField(...));
+                            code.classconstant().setClass(oidType);
+                            code.constant().setValue(name);
+                            code.constant().setValue(true);
+                            code.invokestatic().setMethod(Reflection.class,
+                                "findField", Field.class, new Class[] { 
+                                Class.class, String.class, boolean.class });
+                            code.invokestatic().setMethod
+                                (getReflectionGetterMethod(type, Field.class));
+                            if (!type.isPrimitive() && type != Object.class)
+                                code.checkcast().setType(type);
+                        }
                     }
                 } else {
                     getter = Reflection.findGetter(oidType, name, true);
@@ -4823,4 +4881,116 @@ public class PCEnhancer { 
         }
         return false;
     }
+
+    /**
+     * Read the optimizedIdCopy value from the config (if available)
+     */
+    private void configureOptimizeIdCopy() {
+        if (_repos != null && _repos.getConfiguration() != null) {
+            _optimizeIdCopy = _repos.getConfiguration().getOptimizeIdCopy();
+        }
+    }
+
+    /*
+     * Cycles through all primary keys verifying whether they can and should
+     * be used for faster oid copy.  The field must be private and must
+     * not have a public setter.  If this is the case, the list of pk fields is
+     * returned.  If not, returns null.
+     */
+    private ArrayList<Integer> optimizeIdCopy(Class<?> oidType, FieldMetaData[]
fmds) {
+        // collect all object id fields and verify they 
+        // a) have a private field
+        // b) do not have a public setter 
+        ArrayList<Integer> pkFields = new ArrayList<Integer>();
+        // build list of primary key fields
+        for (int i = 0; i < fmds.length; i++) {
+            if (!fmds[i].isPrimaryKey())
+                continue;
+            // optimizing copy with PC type not (yet) supported
+            if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
+                return null;
+            }
+            String name = fmds[i].getName();
+            Field fld = Reflection.findField(oidType, name, false);
+            if (fld == null || Modifier.isPublic(fld.getModifiers())) {
+                return null;
+            }
+            Method setter = Reflection.findSetter(oidType, name, false);
+            if (setter == null || !Modifier.isPublic(setter.getModifiers())) {
+                pkFields.add(i);
+            } else {
+                return null;
+            }
+        }
+        return pkFields.size() > 0 ? pkFields : null;
+    }
+
+    /*
+     * Cycles through all constructors of an IdClass and examines the instructions to find
+     * a matching constructor for the provided pk fields.  If a match is found, it returns
+     * the order (relative to the field metadata) of the constructor parameters.  If a match
+     * is not found, returns null.
+    */
+    private int[] getIdClassConstructorParmOrder(Class<?> oidType, ArrayList<Integer>
pkfields,
+            FieldMetaData[] fmds) {
+        Project project = new Project();
+        BCClass bc = project.loadClass(oidType);
+        BCMethod[] methods = bc.getDeclaredMethods("<init>");
+        if (methods == null || methods.length == 0) {
+            return null;
+        }
+        
+        int parmOrder[] = new int[pkfields.size()];
+        for (BCMethod method : methods) {
+            // constructor must be public
+            if (!method.isPublic()) {
+                continue;
+            }
+            Class<?>[] parmTypes = method.getParamTypes();
+            // make sure the constructors have the same # of parms as 
+            // the number of pk fields
+            if (parmTypes.length != pkfields.size()) {
+                continue;
+            }
+            
+            int parmOrderIndex = 0;
+            Code code = method.getCode(false);
+            Instruction[] ins = code.getInstructions();
+            for (int i = 0; i < ins.length; i++) {
+                if (ins[i] instanceof PutFieldInstruction) {
+                    PutFieldInstruction pfi = (PutFieldInstruction)ins[i];
+                    for (int j = 0; j < pkfields.size(); j++) {
+                        int fieldNum = pkfields.get(j);
+                        // Compare the field being set with the current pk field
+                        String parmName = fmds[fieldNum].getName();
+                        Class<?> parmType = fmds[fieldNum].getType();
+                        if (parmName.equals(pfi.getFieldName())) {
+                            // backup and examine the load instruction parm
+                            if (i > 0 && ins[i-1] instanceof LoadInstruction)
{
+                                LoadInstruction li = (LoadInstruction)ins[i-1];
+                                // Get the local index from the instruction.  This will be
the index
+                                // of the constructor parameter.  must be less than or equal
to the 
+                                // max parm index to prevent from picking up locals that
could have
+                                // been produced within the constructor.  Also make sure
the parm type
+                                // matches the fmd type
+                                int parm = li.getLocal();
+                                if (parm <= pkfields.size() && parmTypes[parm-1].equals(parmType))
{
+                                    parmOrder[parmOrderIndex] = fieldNum;
+                                    parmOrderIndex++;
+                                }
+                            } else {
+                                // Some other instruction found. can't make a determination
of which local/parm
+                                // is being used on the putfield.
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            if (parmOrderIndex == pkfields.size()) {
+                return parmOrder;
+            }
+        }
+        return null;
+    }
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
(original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
Mon Feb  6 22:03:02 2012
@@ -576,6 +576,14 @@ public class ApplicationIds {
     }
 
     /**
+     * Sets the underlying id of an ObjectId.  Should only
+     * be used with simple (idclass) types.
+     */
+    public static void setAppId(ObjectId id, Object newId) {
+        id.setId(newId);
+    }
+
+    /**
      * Helper class used to transfer pk values to/from application oids.
      */
     private static class PrimaryKeyFieldManager

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml?rev=1241207&r1=1241206&r2=1241207&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/ant/enhancer.xml Mon Feb  6 22:03:02 2012
@@ -31,12 +31,12 @@
         <istrue value="${maven.test.skip}" />
     </condition>
 
-	<condition property="skip.enhance">
-		<or>
+    <condition property="skip.enhance">
+        <or>
         <equals arg1="${test}" arg2="false" />
-			<equals arg1="${build.enhance}" arg2="false" />
-			<istrue value="${maven.test.skip}" />
-			<istrue value="${skipTests}" />
+        <equals arg1="${build.enhance}" arg2="false" />
+        <istrue value="${maven.test.skip}" />
+        <istrue value="${skipTests}" />
         </or>
     </condition>
 
@@ -83,7 +83,8 @@
             <exclude name="org/apache/openjpa/enhance/EnhancedSubClass.class"/>
             <exclude name="**/AbstractUnenhanced*.class" />
             <exclude name="**/unenhanced/*.class" />
-			<exclude name="**/persistence/property/AccessModsEntity.class"/>
+            <exclude name="**/persistence/property/AccessModsEntity.class"/>
+            <exclude name="org/apache/openjpa/enhance/ids/*.class"/>
         </fileset>
         <openjpac>
             <classpath refid="cp" />
@@ -99,17 +100,17 @@
                 <include name="**/detach/serializable/*.class" />
                 <!--  include files from orm.xml -->
                 <include name="**/xml/*.class" />
-				<exclude name="**/persistence/delimited/identifiers/xml/*.class"/>
+                <exclude name="**/persistence/delimited/identifiers/xml/*.class"/>
                 <exclude name="**/Test*.class" />
             </fileset>
             <config log="${openjpa.Log}" />
         </openjpac>
-		<!-- Enhance with private persistent properties compatibility option -->
+        <!-- Enhance with private persistent properties compatibility option -->
         <openjpac>
             <config propertiesFile="${project.build.testOutputDirectory}/META-INF/nopriv_persistence.xml"
/>
             <classpath refid="cp" />
             <fileset dir="${project.build.testOutputDirectory}">
-				<include name="**/persistence/property/AccessModsEntity.class"/>
+            <include name="**/persistence/property/AccessModsEntity.class"/>
             </fileset>
             <config log="${openjpa.Log}" />
         </openjpac>
@@ -132,15 +133,24 @@
             </fileset>
             <config log="${openjpa.Log}" />
         </openjpac>
-		<!-- Enhance delimited identifiers XML-based entities separately -->
+        <!-- Enhance delimited identifiers XML-based entities separately -->
         <openjpac>
             <config propertiesFile="${project.build.testOutputDirectory}/META-INF/delim_persistence.xml"
/>
             <classpath refid="cp" />
             <fileset dir="${project.build.testOutputDirectory}">
-				<include name="**/persistence/delimited/identifiers/xml/*.class"/>
-				<exclude name="**/persistence/delimited/identifiers/xml/Test*.class"/>
+                <include name="**/persistence/delimited/identifiers/xml/*.class"/>
+                <exclude name="**/persistence/delimited/identifiers/xml/Test*.class"/>
             </fileset>
             <config log="${openjpa.Log}"/>
         </openjpac>
+        <!-- Enhance with optimized id copy option -->
+        <openjpac>
+            <config propertiesFile="${project.build.testOutputDirectory}/META-INF/optidcpy_persistence.xml"
/>
+            <classpath refid="cp" />
+            <fileset dir="${project.build.testOutputDirectory}">
+                <include name="org/apache/openjpa/enhance/ids/*.class"/>
+            </fileset>
+            <config log="${openjpa.Log}" />
+        </openjpac>
     </target>
 </project>

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,70 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="ID_DEVTBL")
+@IdClass(DeviceId.class)
+public class Device {
+
+    @Id
+    @Column(name="DEV_ID")
+    private int id;
+    
+    @Id
+    @Column(name="DEV_TYPE")
+    private int type;
+    
+    @Column(name="DEV_DESC")
+    private String description;
+
+    public Device() {
+        
+    }
+    
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Device.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,67 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+public class DeviceId {
+    
+    public static boolean[] usedConstructor = new boolean[3];
+
+    private int id;
+    
+    private int type;
+    
+    public DeviceId() {
+        usedConstructor[0] = true;
+    }
+    
+    @SuppressWarnings("unused")
+    private DeviceId(int i, int t) {
+        usedConstructor[1] = true;
+        id = i;
+        type = t;
+    }
+    
+    public DeviceId(int i) {
+        usedConstructor[2] = true;
+        id = i;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DeviceId) {
+            DeviceId did = (DeviceId)obj;
+            return did.getId() == getId() &&
+                did.getType() == getType();
+        }
+        return false;
+    }
+    
+    @Override
+    public int hashCode() {
+        return getId() + getType();
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/DeviceId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,65 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Table(name="ID_HWTBL")
+@IdClass(HardwareId.class)
+@Entity
+public class Hardware {
+
+    @Id
+    private String serial;
+    
+    @Id
+    private String model;
+    
+    private String description;
+
+    public Hardware() {
+    }
+    
+    public void setSerial(String serial) {
+        this.serial = serial;
+    }
+
+    public String getSerial() {
+        return serial;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Hardware.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,67 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+public class HardwareId {
+    
+    public static boolean[] usedConstructor = new boolean[2];
+
+    private String serial;
+    
+    private String model;
+    
+    public HardwareId() {
+    }
+    
+    // Parms out of order
+    public HardwareId(String model, String serial) {
+        usedConstructor[0] = true;
+        this.serial = serial;
+        this.model = model;
+    }
+    
+    public HardwareId(String model,int serial) {
+        usedConstructor[1] = true;
+        this.model = model;
+        this.serial = Integer.toString(serial);
+    }
+
+    public String getSerial() {
+        return serial;
+    }
+
+    public String getModel() {
+        return model;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof HardwareId) {
+            HardwareId hid = (HardwareId)obj;
+            return hid.getModel().equals(getModel()) &&
+                hid.getSerial().equals(getSerial());
+        }
+        return false;
+    }
+    
+    @Override
+    public int hashCode() {
+        return getSerial().hashCode() + getModel().hashCode();
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/HardwareId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,68 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="ID_SWTBL")
+@IdClass(SoftwareId.class)
+public class Software {
+        
+    @Id
+    private Integer idInteger;
+    
+    @Id
+    private int idInt;
+    
+    @Id
+    private String idString;
+
+    public Software() {
+        
+    }
+    
+    public void setIdInteger(Integer idInteger) {
+        this.idInteger = idInteger;
+    }
+
+    public Integer getIdInteger() {
+        return idInteger;
+    }
+
+    public void setIdInt(int idInt) {
+        this.idInt = idInt;
+    }
+
+    public int getIdInt() {
+        return idInt;
+    }
+
+    public void setIdString(String idString) {
+        this.idString = idString;
+    }
+
+    public String getIdString() {
+        return idString;
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/Software.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,80 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+public class SoftwareId {
+    
+    public static boolean[] usedConstructor = new boolean[3];
+
+    private Integer idInteger;
+    
+    private int idInt;
+    
+    private String idString;
+    
+    public SoftwareId() {
+        
+    }
+    
+    public SoftwareId(int idint) {
+        usedConstructor[0] = true;
+        idInt = idint;
+    }
+
+    public SoftwareId(Integer idinteger, int idint) {
+        usedConstructor[1] = true;
+        idInteger = idinteger;
+        idInt = idint;
+    }
+
+    public SoftwareId(Integer idinteger, int idint, String idstring) {
+        usedConstructor[2] = true;
+        idInteger = idinteger;
+        idInt = idint;
+        idString =idstring;
+    }
+    public Integer getIdInteger() {
+        return idInteger;
+    }
+
+    public int getIdInt() {
+        return idInt;
+    }
+
+    public String getIdString() {
+        return idString;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof SoftwareId) {
+            SoftwareId swid = (SoftwareId)obj;
+            return swid.getIdInt() == getIdInt() &&
+                swid.getIdInteger().equals(getIdInteger()) &&
+                swid.getIdString().equals(getIdString());
+        }
+        return false;
+    }
+    
+    @Override
+    public int hashCode() {
+        return getIdInt() + getIdInteger().hashCode() + getIdString().hashCode();
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/SoftwareId.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,122 @@
+/*
+ * 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.openjpa.enhance.ids;
+
+import java.util.List;
+import java.util.Random;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Verifies the use of the openjpa.OptimizeIdCopy configuration parameter.  This parameter
+ * changes the behavior of the enhancer and thus, must be set before enhancement occurs.
 There
+ * is special enhancement task in main/ant/enhancer.xml to ensure this value is set
+ * during the enhancement process for the entities used by this test.
+ */
+public class TestOptimizeIdCopy extends SingleEMFTestCase {
+    
+    @Override
+    public void setUp() {
+        setUp(Device.class,Hardware.class,Software.class, CLEAR_TABLES);
+    }
+    
+    /*
+     * Verifies that constructor-based Id optimization occurs during Id copy. Asserts
+     * only the proper/expected public constructor is called during the id copy operation.
+     */
+    public void testIdOptimization() {
+        EntityManager em = emf.createEntityManager();
+        
+        // Add a software entity
+        Software sw = new Software();
+        int id = new Random().nextInt();
+        sw.setIdInt(id);
+        sw.setIdInteger(10);
+        sw.setIdString("StringIdVal");
+        
+        em.getTransaction().begin();
+        em.persist(sw);
+        em.getTransaction().commit();
+        em.clear();
+        
+        TypedQuery<Software> swq = em.createQuery("select sw from Software sw", Software.class);
+        List<Software> swl = swq.getResultList();
+        assertTrue("Software result list > 0", swl.size() > 0);
+        // Id copy optimization should have used the 3rd constructor
+        assertFalse("First constructor was not used", SoftwareId.usedConstructor[0]);
+        assertFalse("Second constructor was not used", SoftwareId.usedConstructor[1]);
+        assertTrue("Third (correct) constructor was used", SoftwareId.usedConstructor[2]);
+        em.close();
+    }
+    
+    /*
+     * Verifies that constructor based optimization functions even if parms
+     * are different than field order
+     */
+    public void testIdOptimizationConstructorOutOfOrder() {
+        EntityManager em = emf.createEntityManager();
+        
+        Hardware hw = new Hardware();
+        String id = "Model" + (new Random().nextInt());
+        hw.setModel("Model" + id);
+        hw.setSerial("123XYZ");
+        
+        em.getTransaction().begin();
+        em.persist(hw);
+        em.getTransaction().commit();
+        em.clear();
+        
+        TypedQuery<Hardware> hwq = em.createQuery("select hw from Hardware hw", Hardware.class);
+        List<Hardware> hwl = hwq.getResultList();
+        assertTrue("Hardware result list > 0", hwl.size() > 0);
+        // Id copy optimization should have used the first constructor
+        assertTrue("First (correct) constructor was used", HardwareId.usedConstructor[0]);
+        assertFalse("Second constructor was not used", HardwareId.usedConstructor[1]);
+        em.close();
+    }
+    
+    /*
+     * Verifies that classes without a proper constructor do not get optimized
+     */
+    public void testNoOptimization() {
+        EntityManager em = emf.createEntityManager();
+        
+        int id = new Random().nextInt();
+        Device d = new Device();
+        d.setId(id);
+        d.setType(10);
+        
+        em.getTransaction().begin();
+        em.persist(d);
+        em.getTransaction().commit();
+        em.clear();
+
+        TypedQuery<Device> dq = em.createQuery("select d from Device d", Device.class);
+        List<Device> dl = dq.getResultList();
+        assertTrue("Device result list > 0", dl.size() > 0);
+        // Only the first, default constructor should have been called
+        assertTrue("First (default) constructor was used", DeviceId.usedConstructor[0]);
+        assertFalse("Second constructor was not used", DeviceId.usedConstructor[1]);
+        assertFalse("Third constructor was not used", DeviceId.usedConstructor[2]);
+        em.close();
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/ids/TestOptimizeIdCopy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml?rev=1241207&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
(added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
Mon Feb  6 22:03:02 2012
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.   
+-->
+<persistence
+    xmlns="http://java.sun.com/xml/ns/persistence"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
+        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+    version="2.0" >
+
+   <persistence-unit name="OptimizeIdCopy_PU">
+        <description>
+            This PU
+        </description>
+        <class>org.apache.openjpa.enhance.ids.Device</class>
+        <class>org.apache.openjpa.enhance.ids.Hardware</class>
+        <class>org.apache.openjpa.enhance.ids.Software</class>
+        <properties>
+           <property name="openjpa.OptimizeIdCopy" value="true"/>
+        </properties>
+    </persistence-unit>
+</persistence>
\ No newline at end of file

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/META-INF/optidcpy_persistence.xml
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message