diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/CodeGenerator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/CodeGenerator.java index 5cdee2c16..f0ff6ac30 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/CodeGenerator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/CodeGenerator.java @@ -398,14 +398,24 @@ public class CodeGenerator { code.append("is"); else code.append("get"); - code.append(capFieldName).parens(); + if (fieldName.length() > 1 && Character.isLowerCase(fieldName.charAt(0)) + && Character.isUpperCase(fieldName.charAt(1))) { + code.append(fieldName).parens(); + } else { + code.append(capFieldName).parens(); + } code.openBrace(2).endl(); code.tab(2).append("return ").append(fieldName). append(";").endl(); code.closeBrace(2).afterSection(); // setter - code.tab().append("public void set").append(capFieldName); + if (fieldName.length() > 1 && Character.isLowerCase(fieldName.charAt(0)) + && Character.isUpperCase(fieldName.charAt(1))) { + code.tab().append("public void set").append(fieldName); + } else { + code.tab().append("public void set").append(capFieldName); + } code.openParen(true).append(fieldType).append(paramType). append(" ").append(propertyName).closeParen(); code.openBrace(2).endl(); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index 7b4fd95af..e6f592f24 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -806,7 +806,7 @@ public class PCEnhancer { * Return the name of the setter method for the given field. */ private static String getSetterName(FieldMetaData fmd) { - return "set" + StringUtils.capitalize(fmd.getName()); + return fmd.getSetterName(); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java index 6fc514350..9765de30f 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/Reflection.java @@ -123,6 +123,19 @@ public class Reflection { || m.getReturnType() == Boolean.class)) { setGetterMethod(cls, prop, m); return m; + } else { + m = getDeclaredMethod(c, "get" + prop, null); + if (m != null) { + setGetterMethod(cls, prop, m); + return m; + } else { + m = getDeclaredMethod(c, "is" + prop, null); + if (m != null + && (m.getReturnType() == boolean.class || m.getReturnType() == Boolean.class)) { + setGetterMethod(cls, prop, m); + return m; + } + } } } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java index c30b48f9b..4e5824dd4 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java @@ -2446,4 +2446,26 @@ public class FieldMetaData public void setUseSchemaElement(boolean _useSchemaElement) { this._useSchemaElement = _useSchemaElement; } + + public String getSetterName() { + String setterName = "set" + StringUtils.capitalize(_name); + if (_name.length() > 1 && Character.isLowerCase(_name.charAt(0)) && Character.isUpperCase(_name.charAt(1))) { + // We have the special case where the first char is lower, and the + // following char is capital. We need to support using the + // setaStart() (correct) and setAStart() (incorrect -- old way) + Class type = getDeclaringMetaData().getDescribedType(); + setterName = "set" + _name; + try { + type.getDeclaredMethod(setterName, getType()); + return setterName; + } catch (Exception e) { + } + setterName = "set" + StringUtils.capitalize(_name); + try { + type.getDeclaredMethod(setterName, getType()); + } catch (Exception e) { + } + } + return setterName; + } } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalization.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalization.java new file mode 100644 index 000000000..8281172b1 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalization.java @@ -0,0 +1,217 @@ +/* + * 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.persistence.access; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "CAPITALIZATION_TABLE") +public class PropertyAccessCapitalization { + private long id; + private int word; + private int aWord; + private int aaWord; + private int aaaWord; + private int CAPITAL; + private int aCAPITAL; + private int Another; + private int a1; + private int B1; + private int a; + private int B; + private boolean aBoolean; + private boolean BBoolean; + private boolean BOOLEAN; + private boolean Bool; + + public int getaCAPITAL() { + return aCAPITAL; + } + + public void setaCAPITAL(int aCAPITAL) { + this.aCAPITAL = aCAPITAL; + } + + public int getA1() { + return a1; + } + + public void setA1(int a1) { + this.a1 = a1; + } + + public int getA() { + return a; + } + + public void setA(int a) { + this.a = a; + } + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public int getWord() { + return word; + } + + public void setWord(int word) { + this.word = word; + } + + public int getaWord() { + return aWord; + } + + public void setaWord(int aWord) { + this.aWord = aWord; + } + + public int getAaWord() { + return aaWord; + } + + public void setAaWord(int aaWord) { + this.aaWord = aaWord; + } + + public int getAaaWord() { + return aaaWord; + } + + public void setAaaWord(int aaaWord) { + this.aaaWord = aaaWord; + } + + public int getCAPITAL() { + return CAPITAL; + } + + public void setCAPITAL(int cAPITAL) { + CAPITAL = cAPITAL; + } + + public int getB1() { + return B1; + } + + public void setB1(int b1) { + B1 = b1; + } + + public int getB() { + return B; + } + + public void setB(int b) { + B = b; + } + + public int getAnother() { + return Another; + } + + public void setAnother(int another) { + Another = another; + } + + public boolean isaBoolean() { + return aBoolean; + } + + public void setaBoolean(boolean aBoolean) { + this.aBoolean = aBoolean; + } + + public boolean isBBoolean() { + return BBoolean; + } + + public void setBBoolean(boolean bBoolean) { + BBoolean = bBoolean; + } + + public boolean isBOOLEAN() { + return BOOLEAN; + } + + public void setBOOLEAN(boolean bOOLEAN) { + BOOLEAN = bOOLEAN; + } + + public boolean isBool() { + return Bool; + } + + public void setBool(boolean bool) { + Bool = bool; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PropertyAccessCapitalization other = (PropertyAccessCapitalization) obj; + if (getAnother() != other.getAnother()) + return false; + if (getB() != other.getB()) + return false; + if (getB1() != other.getB1()) + return false; + if (isBBoolean() != other.isBBoolean()) + return false; + if (isBOOLEAN() != other.isBOOLEAN()) + return false; + if (isBool() != other.isBool()) + return false; + if (getCAPITAL() != other.getCAPITAL()) + return false; + if (getA() != other.getA()) + return false; + if (getA1() != other.getA1()) + return false; + if (isaBoolean() != other.isaBoolean()) + return false; + if (getaCAPITAL() != other.getaCAPITAL()) + return false; + if (getaWord() != other.getaWord()) + return false; + if (getAaWord() != other.getAaWord()) + return false; + if (getAaaWord() != other.getAaaWord()) + return false; + if (getId() != other.getId()) + return false; + if (getWord() != other.getWord()) + return false; + return true; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalizationOldBehavior.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalizationOldBehavior.java new file mode 100644 index 000000000..bedbe4928 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/PropertyAccessCapitalizationOldBehavior.java @@ -0,0 +1,220 @@ +/* + * 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.persistence.access; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "CAPITALIZATION_OLD_BEHAVIOR_TABLE") +@Access(AccessType.PROPERTY) +public class PropertyAccessCapitalizationOldBehavior { + private long id; + private int word; + private int aWord; + private int aaWord; + private int aaaWord; + private int CAPITAL; + private int aCAPITAL; + private int Another; + private int a1; + private int B1; + private int a; + private int B; + private boolean aBoolean; + private boolean BBoolean; + private boolean BOOLEAN; + private boolean Bool; + + public int getAWord() { + return aWord; + } + + public void setAWord(int aWord) { + this.aWord = aWord; + } + + @Id + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public int getWord() { + return word; + } + + public void setWord(int word) { + this.word = word; + } + + public int getAaWord() { + return aaWord; + } + + public void setAaWord(int aaWord) { + this.aaWord = aaWord; + } + + public int getAaaWord() { + return aaaWord; + } + + public void setAaaWord(int aaaWord) { + this.aaaWord = aaaWord; + } + + public int getCAPITAL() { + return CAPITAL; + } + + public void setCAPITAL(int cAPITAL) { + CAPITAL = cAPITAL; + } + + public int getACAPITAL() { + return aCAPITAL; + } + + public void setACAPITAL(int aCAPITAL) { + this.aCAPITAL = aCAPITAL; + } + + public int getA1() { + return a1; + } + + public void setA1(int a1) { + this.a1 = a1; + } + + public int getA() { + return a; + } + + public void setA(int a) { + this.a = a; + } + + public int getB1() { + return B1; + } + + public void setB1(int b1) { + B1 = b1; + } + + public int getB() { + return B; + } + + public void setB(int b) { + B = b; + } + + public int getAnother() { + return Another; + } + + public void setAnother(int another) { + Another = another; + } + + public boolean isABoolean() { + return aBoolean; + } + + public void setABoolean(boolean aBoolean) { + this.aBoolean = aBoolean; + } + + public boolean isBBoolean() { + return BBoolean; + } + + public void setBBoolean(boolean bBoolean) { + BBoolean = bBoolean; + } + + public boolean isBOOLEAN() { + return BOOLEAN; + } + + public void setBOOLEAN(boolean bOOLEAN) { + BOOLEAN = bOOLEAN; + } + + public boolean isBool() { + return Bool; + } + + public void setBool(boolean bool) { + Bool = bool; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PropertyAccessCapitalizationOldBehavior other = (PropertyAccessCapitalizationOldBehavior) obj; + if (getAnother() != other.getAnother()) + return false; + if (getB() != other.getB()) + return false; + if (getB1() != other.getB1()) + return false; + if (isBBoolean() != other.isBBoolean()) + return false; + if (isBOOLEAN() != other.isBOOLEAN()) + return false; + if (isBool() != other.isBool()) + return false; + if (getCAPITAL() != other.getCAPITAL()) + return false; + if (getA() != other.getA()) + return false; + if (getA1() != other.getA1()) + return false; + if (isABoolean() != other.isABoolean()) + return false; + if (getACAPITAL() != other.getACAPITAL()) + return false; + if (getAWord() != other.getAWord()) + return false; + if (getAaWord() != other.getAaWord()) + return false; + if (getAaaWord() != other.getAaaWord()) + return false; + if (getId() != other.getId()) + return false; + if (getWord() != other.getWord()) + return false; + return true; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestPropertyAccessCapitalization.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestPropertyAccessCapitalization.java new file mode 100644 index 000000000..fc2d4644c --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestPropertyAccessCapitalization.java @@ -0,0 +1,94 @@ +/* + * 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.persistence.access; + +import java.util.Random; + +import javax.persistence.EntityManager; + +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestPropertyAccessCapitalization extends SingleEMFTestCase { + public void setUp() { + setUp(DROP_TABLES, PropertyAccessCapitalization.class, PropertyAccessCapitalizationOldBehavior.class); + } + + public void testCorrectCapitalization() { + EntityManager em = emf.createEntityManager(); + + PropertyAccessCapitalization entity = new PropertyAccessCapitalization(); + Random r = new Random(); + entity.setId(r.nextInt()); + entity.setWord(r.nextInt()); + entity.setaWord(r.nextInt()); + entity.setAaWord(r.nextInt()); + entity.setAaaWord(r.nextInt()); + entity.setCAPITAL(r.nextInt()); + entity.setaCAPITAL(r.nextInt()); + entity.setAnother(r.nextInt()); + entity.setA1(r.nextInt()); + entity.setB1(r.nextInt()); + entity.setA(r.nextInt()); + entity.setB(r.nextInt()); + entity.setaBoolean(true); + entity.setBBoolean(true); + entity.setBOOLEAN(true); + entity.setBool(true); + + em.getTransaction().begin(); + em.persist(entity); + em.getTransaction().commit(); + + em.clear(); + PropertyAccessCapitalization persistentEntity = em.find(PropertyAccessCapitalization.class, entity.getId()); + assertEquals(entity, persistentEntity); + } + + public void testOldCapitalization() { + EntityManager em = emf.createEntityManager(); + + PropertyAccessCapitalizationOldBehavior entity = new PropertyAccessCapitalizationOldBehavior(); + Random r = new Random(); + entity.setId(r.nextInt()); + entity.setWord(r.nextInt()); + entity.setAWord(r.nextInt()); + entity.setAaWord(r.nextInt()); + entity.setAaaWord(r.nextInt()); + entity.setCAPITAL(r.nextInt()); + entity.setACAPITAL(r.nextInt()); + entity.setAnother(r.nextInt()); + entity.setA1(r.nextInt()); + entity.setB1(r.nextInt()); + entity.setA(r.nextInt()); + entity.setB(r.nextInt()); + entity.setABoolean(true); + entity.setBBoolean(true); + entity.setBOOLEAN(true); + entity.setBool(true); + + em.getTransaction().begin(); + em.persist(entity); + em.getTransaction().commit(); + + em.clear(); + PropertyAccessCapitalizationOldBehavior persistentEntity = + em.find(PropertyAccessCapitalizationOldBehavior.class, entity.getId()); + assertEquals(entity, persistentEntity); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java index ffc00dc24..2b8e61fce 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java @@ -609,12 +609,16 @@ public class PersistenceMetaDataDefaults return false; } try { + String setterName; + if (member.getName().startsWith("is")) { + setterName = "set" + member.getName().substring(2); + } else { + setterName = "set" + member.getName().substring(3); + } // check for setters for methods - Method setter = (Method) AccessController.doPrivileged( - J2DoPrivHelper.getDeclaredMethodAction( - meta.getDescribedType(), "set" + - StringUtils.capitalize(name), new Class[] { - ((Method) member).getReturnType() })); + Method setter = + (Method) AccessController.doPrivileged(J2DoPrivHelper.getDeclaredMethodAction( + meta.getDescribedType(), setterName, new Class[] { ((Method) member).getReturnType() })); if (setter == null && !isAnnotatedTransient(member)) { logNoSetter(meta, name, null); return false;