From f9fd4837b316ad205d27cdf053cf51b757080f8a Mon Sep 17 00:00:00 2001 From: Fay Wang Date: Thu, 30 Apr 2009 19:07:18 +0000 Subject: [PATCH] OPENJPA-1055: add MapKeyTemporal and MapKeyEnumerated support git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@770400 13f79535-47bb-0310-9956-ffa450edef68 --- .../HandlerHandlerMapTableFieldStrategy.java | 13 +-- .../AnnotationPersistenceMappingParser.java | 46 ++++++++++ .../openjpa/persistence/jdbc/MappingTag.java | 2 + .../jdbc/XMLPersistenceMappingParser.java | 54 ++++++++++++ .../openjpa/persistence/embed/FileName4.java | 68 +++++++++++++++ .../openjpa/persistence/embed/Item4.java | 65 ++++++++++++++ .../openjpa/persistence/embed/Item5.java | 66 ++++++++++++++ .../persistence/embed/TestEmbeddable.java | 85 ++++++++++++++++++- 8 files changed, 388 insertions(+), 11 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/FileName4.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item4.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item5.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java index 4d8aa6cd9..e7a714c06 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java @@ -109,15 +109,10 @@ public class HandlerHandlerMapTableFieldStrategy field.mapJoin(adapt, true); _kio = new ColumnIO(); List columns = key.getValueInfo().getColumns(); - if (columns != null && columns.size() > 0) { - // MapKeyColumn is used - _kcols = HandlerStrategies.map(key, "key", _kio, adapt); - } else { - DBDictionary dict = field.getMappingRepository().getDBDictionary(); - _kcols = HandlerStrategies.map(key, - dict.getValidColumnName("key", field.getTable()), _kio, - adapt); - } + DBDictionary dict = field.getMappingRepository().getDBDictionary(); + String colName = dict.getValidColumnName("key", field.getTable()); + _kcols = HandlerStrategies.map(key, colName, _kio, adapt); + _vio = new ColumnIO(); _vcols = HandlerStrategies.map(val, "value", _vio, adapt); field.mapPrimaryKey(adapt); diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java index 4a2737990..77a07bbdf 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java @@ -45,8 +45,10 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinColumns; import javax.persistence.JoinTable; import javax.persistence.MapKeyColumn; +import javax.persistence.MapKeyEnumerated; import javax.persistence.MapKeyJoinColumn; import javax.persistence.MapKeyJoinColumns; +import javax.persistence.MapKeyTemporal; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.PrimaryKeyJoinColumns; import javax.persistence.SecondaryTable; @@ -145,8 +147,10 @@ public class AnnotationPersistenceMappingParser _tags.put(KeyNonpolymorphic.class, KEY_NONPOLY); _tags.put(KeyStrategy.class, KEY_STRAT); _tags.put(MapKeyColumn.class, MAP_KEY_COL); + _tags.put(MapKeyEnumerated.class, MAP_KEY_ENUMERATED); _tags.put(MapKeyJoinColumn.class, MAP_KEY_JOIN_COL); _tags.put(MapKeyJoinColumns.class, MAP_KEY_JOIN_COLS); + _tags.put(MapKeyTemporal.class, MAP_KEY_TEMPORAL); _tags.put(PrimaryKeyJoinColumn.class, PK_JOIN_COL); _tags.put(PrimaryKeyJoinColumns.class, PK_JOIN_COLS); _tags.put(SecondaryTable.class, SECONDARY_TABLE); @@ -1070,6 +1074,9 @@ public class AnnotationPersistenceMappingParser case MAP_KEY_COL: parseMapKeyColumn(fm, (MapKeyColumn) anno); break; + case MAP_KEY_ENUMERATED: + parseMapKeyEnumerated(fm, (MapKeyEnumerated) anno); + break; case MAP_KEY_JOIN_COL: parseMapKeyJoinColumns(fm, (MapKeyJoinColumn) anno); break; @@ -1091,6 +1098,9 @@ public class AnnotationPersistenceMappingParser case TEMPORAL: parseTemporal(fm, (Temporal) anno); break; + case MAP_KEY_TEMPORAL: + parseMapKeyTemporal(fm, (MapKeyTemporal) anno); + break; case CLASS_CRIT: fm.getValueInfo().setUseClassCriteria (((ClassCriteria) anno).value()); @@ -1350,6 +1360,15 @@ public class AnnotationPersistenceMappingParser fm.getValueInfo().setStrategy(strat); } + /** + * Parse @MapKeyEnumerated. + */ + private void parseMapKeyEnumerated(FieldMapping fm, MapKeyEnumerated anno) { + String strat = EnumValueHandler.class.getName() + "(StoreOrdinal=" + + String.valueOf(anno.value() == EnumType.ORDINAL) + ")"; + fm.getKeyMapping().getValueInfo().setStrategy(strat); + } + /** * Parse @Temporal. */ @@ -1377,6 +1396,33 @@ public class AnnotationPersistenceMappingParser } } + /** + * Parse @Temporal. + */ + private void parseMapKeyTemporal(FieldMapping fm, MapKeyTemporal anno) { + List cols = fm.getKeyMapping().getValueInfo().getColumns(); + if (!cols.isEmpty() && cols.size() != 1) + throw new MetaDataException(_loc.get("num-cols-mismatch", fm, + String.valueOf(cols.size()), "1")); + if (cols.isEmpty()) { + cols = Arrays.asList(new Column[]{ new Column() }); + fm.getKeyMapping().getValueInfo().setColumns(cols); + } + + Column col = (Column) cols.get(0); + switch (anno.value()) { + case DATE: + col.setType(Types.DATE); + break; + case TIME: + col.setType(Types.TIME); + break; + case TIMESTAMP: + col.setType(Types.TIMESTAMP); + break; + } + } + /** * Parse @Column(s). */ diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java index 94ff7c04f..b79bb93e8 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java @@ -49,6 +49,7 @@ enum MappingTag { JOIN_COL, JOIN_COLS, JOIN_TABLE, + MAP_KEY_ENUMERATED, ORDER_COLUMN, PK_JOIN_COL, PK_JOIN_COLS, @@ -92,6 +93,7 @@ enum MappingTag { MAP_KEY_COL, MAP_KEY_JOIN_COL, MAP_KEY_JOIN_COLS, + MAP_KEY_TEMPORAL, MAPPING_OVERRIDE, MAPPING_OVERRIDES, NONPOLY, diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java index c82ea4837..39cee53a4 100644 --- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java +++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/XMLPersistenceMappingParser.java @@ -92,8 +92,10 @@ public class XMLPersistenceMappingParser _elems.put("join-column", JOIN_COL); _elems.put("inverse-join-column", COL); _elems.put("join-table", JOIN_TABLE); + _elems.put("map-key-enumerated", MAP_KEY_ENUMERATED); _elems.put("map-key-column", MAP_KEY_COL); _elems.put("map-key-join-column", MAP_KEY_JOIN_COL); + _elems.put("map-key-temporal", MAP_KEY_TEMPORAL); _elems.put("order-column", ORDER_COLUMN); _elems.put("primary-key-join-column", PK_JOIN_COL); _elems.put("secondary-table", SECONDARY_TABLE); @@ -242,6 +244,8 @@ public class XMLPersistenceMappingParser break; case TEMPORAL: case ENUMERATED: + case MAP_KEY_ENUMERATED: + case MAP_KEY_TEMPORAL: ret = true; break; case SQL_RESULT_SET_MAPPING: @@ -298,9 +302,15 @@ public class XMLPersistenceMappingParser case TEMPORAL: endTemporal(); break; + case MAP_KEY_TEMPORAL: + endMapKeyTemporal(); + break; case ENUMERATED: endEnumerated(); break; + case MAP_KEY_ENUMERATED: + endMapKeyEnumerated(); + break; case SQL_RESULT_SET_MAPPING: endSQLResultSetMapping(); break; @@ -495,6 +505,35 @@ public class XMLPersistenceMappingParser _temporal = Enum.valueOf(TemporalType.class, temp); } + /** + * Parse temporal. + */ + private void endMapKeyTemporal() { + String temp = currentText(); + TemporalType _mapKeyTemporal = null; + if (!StringUtils.isEmpty(temp)) + _mapKeyTemporal = Enum.valueOf(TemporalType.class, temp); + FieldMapping fm = (FieldMapping) currentElement(); + List cols = fm.getKeyMapping().getValueInfo().getColumns(); + if (cols.isEmpty()) { + cols = Arrays.asList(new Column[]{ new Column() }); + fm.getKeyMapping().getValueInfo().setColumns(cols); + } + + Column col = (Column) cols.get(0); + switch (_mapKeyTemporal) { + case DATE: + col.setType(Types.DATE); + break; + case TIME: + col.setType(Types.TIME); + break; + case TIMESTAMP: + col.setType(Types.TIMESTAMP); + break; + } + } + /** * Parse enumerated. */ @@ -510,6 +549,21 @@ public class XMLPersistenceMappingParser fm.getValueInfo().setStrategy(strat); } + /** + * Parse map-key-enumerated. + */ + private void endMapKeyEnumerated() { + String text = currentText(); + if (StringUtils.isEmpty(text)) + return; + EnumType type = Enum.valueOf(EnumType.class, text); + + FieldMapping fm = (FieldMapping) currentElement(); + String strat = EnumValueHandler.class.getName() + "(StoreOrdinal=" + + String.valueOf(type == EnumType.ORDINAL) + ")"; + fm.getKeyMapping().getValueInfo().setStrategy(strat); + } + @Override protected boolean startLob(Attributes attrs) throws SAXException { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/FileName4.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/FileName4.java new file mode 100644 index 000000000..f400267ce --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/FileName4.java @@ -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.persistence.embed; + +import javax.persistence.Embeddable; + +@Embeddable +public class FileName4 { + + String fName; + String lName; + + public FileName4() {} + + public FileName4(String fName, String lName) { + this.fName = fName; + this.lName = lName; + } + + public String getFName() { + return fName; + } + + public void setFName(String fName) { + this.fName = fName; + } + + public String getLName() { + return lName; + } + + public void setLName(String lName) { + this.lName = lName; + } + + public boolean equals(Object o) { + if (!(o instanceof FileName4)) return false; + FileName4 other = (FileName4) o; + if (fName.equals(other.fName) && + lName.equals(other.lName)) + return true; + return false; + } + + public int hashCode() { + int ret = 0; + ret += lName.hashCode(); + ret = 31 * ret + fName.hashCode(); + return ret; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item4.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item4.java new file mode 100644 index 000000000..b2e90b173 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item4.java @@ -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.persistence.embed; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Id; +import javax.persistence.MapKeyEnumerated; + +@Entity +public class Item4 { + @Id + int id; + + @ElementCollection + @MapKeyEnumerated(EnumType.STRING) + Map images = new HashMap(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getImages() { + return images; + } + + public void addImage(Catagory cat, FileName4 fileName) { + images.put(cat, fileName); + } + + public void removeImage(Catagory cat) { + images.remove(cat); + } + + public FileName4 getImage(Catagory cat) { + return images.get(cat); + } + + public enum Catagory { A1, A2, A3, A4 }; + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item5.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item5.java new file mode 100644 index 000000000..62f80ee04 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item5.java @@ -0,0 +1,66 @@ +/* + * 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.embed; + +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Id; +import javax.persistence.MapKeyEnumerated; +import javax.persistence.MapKeyTemporal; +import javax.persistence.TemporalType; + +@Entity +public class Item5 { + @Id + int id; + + @ElementCollection + @MapKeyTemporal(TemporalType.TIME) + Map images = new HashMap(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Map getImages() { + return images; + } + + public void addImage(Timestamp ts, FileName4 fileName) { + images.put(ts, fileName); + } + + public void removeImage(Timestamp ts) { + images.remove(ts); + } + + public FileName4 getImage(Timestamp ts) { + return images.get(ts); + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java index cea88a438..4c082d7d8 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.embed; +import java.sql.Timestamp; import java.util.Collection; import java.util.Date; import java.util.HashMap; @@ -77,7 +78,8 @@ public class TestEmbeddable extends SingleEMFTestCase { Department1.class, Employee1.class, Department2.class, Employee2.class, EmployeePK2.class, Department3.class, Employee3.class, EmployeeName3.class, Item1.class, Item2.class, - Item3.class, Company1.class, Company2.class, Division.class, + Item3.class, Item4.class, Item5.class, FileName4.class, + Company1.class, Company2.class, Division.class, VicePresident.class, EntityA_Embed_MappedToOne.class, Embed_MappedToOne.class, Embed_MappedToOneCascadeDelete.class, EntityA_Embed_MappedToOneCascadeDelete.class, EntityB2.class, @@ -162,6 +164,16 @@ public class TestEmbeddable extends SingleEMFTestCase { findObjMapKeyClass(); } + public void testMapKeyEnumerated() { + createObjMapKeyEnumerated(); + findObjMapKeyEnumerated(); + } + + public void testMapKeyTemporal() { + createObjMapKeyTemporal(); + findObjMapKeyTemporal(); + } + public void testEntityA_Embed_MappedToOneCascadeDelete() { createEntityA_Embed_MappedToOneCascadeDelete(); updateEntityA_Embed_MappedToOneCascadeDelete(); @@ -1576,7 +1588,54 @@ public class TestEmbeddable extends SingleEMFTestCase { tran.commit(); em.close(); } + + public void createObjMapKeyEnumerated() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + Item4 item = new Item4(); + item.setId(1); + FileName4 fileName1 = new FileName4("file" + 1, "file" + 1); + item.addImage(Item4.Catagory.A1, fileName1); + + FileName4 fileName2 = new FileName4("file" + 2, "file" + 2); + item.addImage(Item4.Catagory.A2, fileName2); + + FileName4 fileName3 = new FileName4("file" + 3, "file" + 3); + item.addImage(Item4.Catagory.A3, fileName3); + + em.persist(item); + tran.begin(); + em.flush(); + tran.commit(); + em.close(); + } + public void createObjMapKeyTemporal() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + Item5 item = new Item5(); + item.setId(1); + long ts = System.currentTimeMillis(); + Timestamp ts1 = new Timestamp(ts); + Timestamp ts2 = new Timestamp(ts+1000000); + Timestamp ts3 = new Timestamp(ts+2000000); + + FileName4 fileName1 = new FileName4("file" + 1, "file" + 1); + item.addImage(ts1, fileName1); + + FileName4 fileName2 = new FileName4("file" + 2, "file" + 2); + item.addImage(ts2, fileName2); + + FileName4 fileName3 = new FileName4("file" + 3, "file" + 3); + item.addImage(ts3, fileName3); + + em.persist(item); + tran.begin(); + em.flush(); + tran.commit(); + em.close(); + } + public void createObjMapKeyClass() { EntityManager em = emf.createEntityManager(); EntityTransaction tran = em.getTransaction(); @@ -1920,7 +1979,7 @@ public class TestEmbeddable extends SingleEMFTestCase { int id = vp.getId(); String name = vp.getName(); } - + public void queryObjMapKeyClass() { queryItem(emf); queryCompany(emf); @@ -1928,6 +1987,28 @@ public class TestEmbeddable extends SingleEMFTestCase { queryVicePresident(emf); } + public void findObjMapKeyEnumerated() { + EntityManager em = emf.createEntityManager(); + Item4 item = em.find(Item4.class, 1); + FileName4 fileName1 = item.getImage(Item4.Catagory.A1); + assertEquals("file1", fileName1.getFName()); + assertEquals("file1", fileName1.getLName()); + + FileName4 fileName2 = item.getImage(Item4.Catagory.A2); + assertEquals("file2", fileName2.getFName()); + assertEquals("file2", fileName2.getLName()); + + FileName4 fileName3 = item.getImage(Item4.Catagory.A3); + assertEquals("file3", fileName3.getFName()); + assertEquals("file3", fileName3.getLName()); + } + + public void findObjMapKeyTemporal() { + EntityManager em = emf.createEntityManager(); + Item5 item = em.find(Item5.class, 1); + assertEquals(3, item.getImages().size()); + } + public void queryItem(EntityManagerFactory emf) { EntityManager em = emf.createEntityManager(); EntityTransaction tran = em.getTransaction();