Return-Path: Delivered-To: apmail-openjpa-commits-archive@www.apache.org Received: (qmail 31694 invoked from network); 5 Mar 2009 17:31:00 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Mar 2009 17:31:00 -0000 Received: (qmail 60207 invoked by uid 500); 5 Mar 2009 17:31:00 -0000 Delivered-To: apmail-openjpa-commits-archive@openjpa.apache.org Received: (qmail 60183 invoked by uid 500); 5 Mar 2009 17:30:59 -0000 Mailing-List: contact commits-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list commits@openjpa.apache.org Received: (qmail 60155 invoked by uid 99); 5 Mar 2009 17:30:59 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Mar 2009 09:30:59 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Mar 2009 17:30:53 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 72A8923889B7; Thu, 5 Mar 2009 17:30:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r750517 [1/4] - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/ openjpa-kernel/src/... Date: Thu, 05 Mar 2009 17:30:25 -0000 To: commits@openjpa.apache.org From: fancy@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090305173031.72A8923889B7@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: fancy Date: Thu Mar 5 17:30:20 2009 New Revision: 750517 URL: http://svn.apache.org/viewvc?rev=750517&view=rev Log: OPENJPA-879 JPA2 Query support for selecting KEY, ENTRY and VALUE of a Map value Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapEntry.java openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Division.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/TestMany2ManyMap.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Division.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/TestMany2ManyMapEx1.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/EmployeePK.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhonePK.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex2/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex2/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex2/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex2/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex2/TestMany2ManyMapEx2.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/FullName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex3/TestMany2ManyMapEx3.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex4/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex4/Division.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex4/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex4/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex4/TestMany2ManyMapEx4.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex5/TestMany2ManyMapEx5.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex6/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex6/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex6/FullName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex6/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex6/TestMany2ManyMapEx6.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/Division.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/FullName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex7/TestMany2ManyMapEx7.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/FullName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/TestMany2ManyMapEx8.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/FullName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/FullPhoneName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/PhoneNumber.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex9/TestMany2ManyMapEx9.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Department1.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Department2.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Department3.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Employee1.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Employee2.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/Employee3.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/EmployeeName3.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/EmployeePK2.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex0/TestSpec10_1_26.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex2/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex2/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex2/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex2/EmployeePK.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex2/TestSpec10_1_26_Ex2.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/Department.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/Employee.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/EmployeeName.java openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex3/TestSpec10_1_26_Ex3.java Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java (original) +++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java Thu Mar 5 17:30:20 2009 @@ -408,6 +408,14 @@ return new Type((Val) val); } + public Value mapEntry(Value key, Value val) { + return new MapEntry((Val) key, (Val) val); + } + + public Value mapKey(Value key, Value val) { + return new MapKey((Val) key, (Val) val); + } + public Value getObjectId(Value val) { if (val instanceof Const) return new ConstGetObjectId((Const) val); Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapEntry.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapEntry.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapEntry.java (added) +++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapEntry.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,162 @@ +/* + * 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.jdbc.kernel.exps; + +import java.sql.SQLException; +import java.util.Map; + +import org.apache.openjpa.jdbc.sql.Result; +import org.apache.openjpa.jdbc.sql.SQLBuffer; +import org.apache.openjpa.jdbc.sql.Select; +import org.apache.openjpa.meta.ClassMetaData; + +/** + * Returns the Map.Entry of a map value. + * + * @author Catalina Wei + * @since 2.0.0 + */ +public class MapEntry + extends AbstractVal { + + private final Val _key; + private final Val _val; + private ClassMetaData _meta = null; + private Class _cast = null; + private Class _type = null; + + /** + * Constructor. Provide the map value to operate on. + */ + public MapEntry(Val key, Val val) { + ((PCPath) key).getKey(); + _key = key; + _val = val; + } + + /** + * Expression state. + */ + public static class EntryExpState + extends ExpState { + public ExpState key; + public ExpState val; + + EntryExpState(ExpState key, ExpState val) { + this.key = key; + this.val = val; + } + } + + public void appendTo(Select sel, ExpContext ctx, ExpState state, + SQLBuffer sql, int index) { + } + + public void calculateValue(Select sel, ExpContext ctx, ExpState state, + Val other, ExpState otherState) { + _val.calculateValue(sel, ctx, state, other, otherState); + _key.calculateValue(sel, ctx, state, other, otherState); + } + + public void groupBy(Select sel, ExpContext ctx, ExpState state) { + } + + public ExpState initialize(Select sel, ExpContext ctx, int flags) { + ExpState val = _val.initialize(sel, ctx, flags); + ExpState key = _key.initialize(sel, ctx, flags); + return new EntryExpState(key, val); + } + + public int length(Select sel, ExpContext ctx, ExpState state) { + return 1; + } + + public Object load(ExpContext ctx, ExpState state, Result res) + throws SQLException { + EntryExpState estate = (EntryExpState) state; + Object key = _key.load(ctx, estate.key, res); + Object val = _val.load(ctx, estate.val, res); + + return new Entry(key, val); + } + + public void orderBy(Select sel, ExpContext ctx, ExpState state, boolean asc) { + } + + public void select(Select sel, ExpContext ctx, ExpState state, boolean pks) { + EntryExpState estate = (EntryExpState) state; + _key.selectColumns(sel, ctx, estate.key, pks); + _val.selectColumns(sel, ctx, estate.val, pks); + } + + public void selectColumns(Select sel, ExpContext ctx, ExpState state, + boolean pks) { + } + + public ClassMetaData getMetaData() { + return _meta; + } + + public Class getType() { + return Map.Entry.class; + } + + public void setImplicitType(Class type) { + } + + public void setMetaData(ClassMetaData meta) { + _meta = meta; + } + + private class Entry implements Map.Entry { + private final K key; + private final V value; + + public Entry(K k, V v) { + key = k; + value = v; + } + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V v) { + throw new UnsupportedOperationException(); + } + + public boolean equals(Object other) { + if (other instanceof Map.Entry == false) + return false; + Map.Entry that = (Map.Entry)other; + return (this.key == null ? + that.getKey() == null : key.equals(that.getKey())) && + (value == null ? + that.getValue() == null : value.equals(that.getValue())); + } + + public int hashCode() { + return (key == null ? 0 : key.hashCode()) ^ + (value == null ? 0 : value.hashCode()); + } + } +} Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java (added) +++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java Thu Mar 5 17:30:20 2009 @@ -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.jdbc.kernel.exps; + +import java.sql.SQLException; + +import org.apache.openjpa.jdbc.sql.Result; +import org.apache.openjpa.jdbc.sql.SQLBuffer; +import org.apache.openjpa.jdbc.sql.Select; +import org.apache.openjpa.meta.ClassMetaData; + +/** + * Returns the key of a map value. + * + * @author Catalina Wei + * @since 2.0.0 + */ +public class MapKey + extends AbstractVal { + + private final Val _key; + private final Val _val; + private ClassMetaData _meta = null; + private Class _cast = null; + private Class _type = null; + + /** + * Constructor. Provide the map value to operate on. + */ + public MapKey(Val key, Val val) { + ((PCPath) key).getKey(); + _key = key; + _val = val; + } + + /** + * Expression state. + */ + public static class KeyExpState + extends ExpState { + public ExpState key; + public ExpState val; + + KeyExpState(ExpState key, ExpState val) { + this.key = key; + this.val = val; + } + } + + public void appendTo(Select sel, ExpContext ctx, ExpState state, + SQLBuffer sql, int index) { + } + + public void calculateValue(Select sel, ExpContext ctx, ExpState state, + Val other, ExpState otherState) { + _val.calculateValue(sel, ctx, state, other, otherState); + _key.calculateValue(sel, ctx, state, other, otherState); + } + + public void groupBy(Select sel, ExpContext ctx, ExpState state) { + } + + public ExpState initialize(Select sel, ExpContext ctx, int flags) { + ExpState val = _val.initialize(sel, ctx, flags); + ExpState key = _key.initialize(sel, ctx, flags); + return new KeyExpState(key, val); + } + + public int length(Select sel, ExpContext ctx, ExpState state) { + return 1; + } + + public Object load(ExpContext ctx, ExpState state, Result res) + throws SQLException { + KeyExpState estate = (KeyExpState) state; + Object key = _key.load(ctx, estate.key, res); + return key; + } + + public void orderBy(Select sel, ExpContext ctx, ExpState state, boolean asc) { + } + + public void select(Select sel, ExpContext ctx, ExpState state, boolean pks) { + KeyExpState estate = (KeyExpState) state; + _key.selectColumns(sel, ctx, estate.key, pks); + } + + public void selectColumns(Select sel, ExpContext ctx, ExpState state, + boolean pks) { + } + + public ClassMetaData getMetaData() { + return _meta; + } + + public Class getType() { + return _key.getType(); + } + + public void setImplicitType(Class type) { + } + + public void setMetaData(ClassMetaData meta) { + _meta = meta; + } +} Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original) +++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Thu Mar 5 17:30:20 2009 @@ -25,11 +25,14 @@ import java.util.ListIterator; import org.apache.commons.lang.ObjectUtils; +import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.meta.ClassMapping; import org.apache.openjpa.jdbc.meta.Discriminator; import org.apache.openjpa.jdbc.meta.FieldMapping; +import org.apache.openjpa.jdbc.meta.JavaSQLTypes; import org.apache.openjpa.jdbc.meta.ValueMapping; +import org.apache.openjpa.jdbc.meta.strats.HandlerRelationMapTableFieldStrategy; import org.apache.openjpa.jdbc.schema.Column; import org.apache.openjpa.jdbc.schema.ForeignKey; import org.apache.openjpa.jdbc.schema.Schemas; @@ -40,6 +43,7 @@ import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.kernel.OpenJPAStateManager; +import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.kernel.exps.CandidatePath; import org.apache.openjpa.lib.util.Localizer; @@ -240,6 +244,8 @@ if (pstate.field == null) return _class; if (_key) { + if (pstate.field.getKey().getValueMappedBy() != null) + return _class; if (pstate.field.getKey().getTypeCode() == JavaTypes.PC) return pstate.field.getKeyMapping().getTypeMapping(); return null; @@ -363,8 +369,8 @@ public FieldMetaData last() { Action act = lastFieldAction(); - return (act == null) ? null : isXPath() ? _xmlfield : - (FieldMetaData) act.data; + return (act == null || act.op == Action.GET_KEY) ? null : isXPath() ? + _xmlfield : (FieldMetaData) act.data; } /** @@ -395,7 +401,8 @@ if (act != null && act.op == Action.GET_XPATH) return ((XMLMetaData) act.data).getType(); - FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data; + FieldMetaData fld = (act == null || act.op == Action.GET_KEY) ? null : + (FieldMetaData) act.data; boolean key = act != null && act.op == Action.GET_KEY; if (fld != null) { switch (fld.getDeclaredTypeCode()) { @@ -437,7 +444,7 @@ Action action; Variable var; Iterator itr = (_actions == null) ? null : _actions.iterator(); - FieldMapping field; + FieldMapping field = null; while (itr != null && itr.hasNext()) { action = (Action) itr.next(); @@ -459,7 +466,13 @@ } else { // move past the previous field, if any field = (action.op == Action.GET_XPATH) ? (FieldMapping) _xmlfield : - (FieldMapping) action.data; + (action.op == Action.GET_KEY) ? field : (FieldMapping) action.data; + + // mark if the next traversal should go through + // the key rather than value + key = action.op == Action.GET_KEY; + forceOuter |= action.op == Action.GET_OUTER; + if (pstate.field != null) { // if this is the second-to-last field and the last is // the related field this field joins to, no need to @@ -472,11 +485,6 @@ rel = traverseField(pstate, key, forceOuter, false); } - // mark if the next traversal should go through - // the key rather than value - key = action.op == Action.GET_KEY; - forceOuter |= action.op == Action.GET_OUTER; - // get mapping for the current field pstate.field = field; owner = pstate.field.getDefiningMapping(); @@ -515,6 +523,11 @@ if (_varName != null) pstate.joins = pstate.joins.setVariable(_varName); + // if last action is key action, avoid redundant joins + if (key) { + return pstate; + } + // if we're not comparing to null or doing an isEmpty, then // join into the data on the final field; obviously we can't do these // joins when comparing to null b/c the whole purpose is to see @@ -740,13 +753,29 @@ if (pks) return mapping.getObjectId(ctx.store, res, null, true, pstate.joins); + if (_key) { + if (pstate.field.getKey().getValueMappedBy() != null) { + Object obj = res.load(mapping, ctx.store, ctx.fetch, + pstate.joins); + StateManagerImpl sm = (StateManagerImpl) + ((PersistenceCapable) obj).pcGetStateManager(); + obj = sm.fetch(_class.getField(pstate.field.getKey(). + getValueMappedBy()).getIndex()); + return obj; + } + else if (pstate.field.getKey().isEmbedded()) + return loadEmbeddedMapKey(ctx, state, res); + } + return res.load(mapping, ctx.store, ctx.fetch, pstate.joins); } Object ret; if (_key) - ret = pstate.field.loadKeyProjection(ctx.store, ctx.fetch, res, - pstate.joins); + // Map key is a java primitive type + // example: Map emps + ret = res.getObject(pstate.cols[0], + JavaSQLTypes.JDBC_DEFAULT, pstate.joins); else ret = pstate.field.loadProjection(ctx.store, ctx.fetch, res, pstate.joins); @@ -755,6 +784,23 @@ return ret; } + private Object loadEmbeddedMapKey(ExpContext ctx, ExpState state, + Result res) throws SQLException { + PathExpState pstate = (PathExpState) state; + // consume keyProjection + PersistenceCapable pc = (PersistenceCapable) res.load(_candidate, + ctx.store, ctx.fetch, pstate.joins); + if (pstate.field.getStrategy() == null || + !(pstate.field.getStrategy() instanceof + HandlerRelationMapTableFieldStrategy)) + throw new RuntimeException("Invalid map field strategy"); + HandlerRelationMapTableFieldStrategy strategy = + (HandlerRelationMapTableFieldStrategy) pstate.field.getStrategy(); + return strategy + .loadKey((OpenJPAStateManager) pc.pcGetStateManager(), + ctx.store, ctx.fetch, res, pstate.joins); + } + public void calculateValue(Select sel, ExpContext ctx, ExpState state, Val other, ExpState otherState) { // we don't create the SQL b/c it forces the Select to cache aliases Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java (original) +++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java Thu Mar 5 17:30:20 2009 @@ -40,7 +40,8 @@ public Type(Val val) { super(val); setMetaData(val.getMetaData()); - _disc = ((ClassMapping) getMetaData()).getDiscriminator(); + if (getMetaData() != null) + _disc = ((ClassMapping) getMetaData()).getDiscriminator(); } public ExpState initialize(Select sel, ExpContext ctx, int flags) { Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java (original) +++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java Thu Mar 5 17:30:20 2009 @@ -416,6 +416,18 @@ public Value type(Value target); /** + * Return the map entry of the given value. + * + * @since 2.0.0 + */ + public Value mapEntry(Value key, Value val); + + /** + * Return the map key of the given value + */ + public Value mapKey(Value key, Value val); + + /** * Return distinct values of the given value. This is typically used * within aggregates, for example: max(distinct(path)) * Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java (original) +++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java Thu Mar 5 17:30:20 2009 @@ -35,6 +35,7 @@ import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.ImplHelper; +import org.apache.openjpa.util.UnsupportedException; import org.apache.openjpa.util.UserException; /** @@ -647,6 +648,14 @@ return new Type((Val) val); } + public Value mapEntry(Value key, Value val) { + throw new UnsupportedException("not implemented yet"); + } + + public Value mapKey(Value key, Value val) { + throw new UnsupportedException("not implemented yet"); + } + public Value getObjectId(Value val) { return new GetObjectId((Val) val); } Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original) +++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Thu Mar 5 17:30:20 2009 @@ -49,6 +49,7 @@ import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; +import org.apache.openjpa.meta.JavaTypes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.meta.ValueMetaData; import org.apache.openjpa.util.InternalException; @@ -958,6 +959,17 @@ case JJTIDENTIFICATIONVARIABLE: return getIdentifier(node); + case JJTQUALIFIEDPATH: + // TODO: to be implemented. + + case JJTQUALIFIEDIDENTIFIER: + // KEY(e), VALUE(e), ENTRY(e) + return getQualifiedIdentifier(onlyChild(node)); + + case JJTGENERALIDENTIFIER: + // KEY(e), VALUE(e) + return getQualifiedIdentifier(onlyChild(node)); + case JJTNOT: return factory.not(getExpression(onlyChild(node))); @@ -1412,6 +1424,35 @@ new Object[]{ name }, null); } + private Value getQualifiedIdentifier(JPQLNode node) { + JPQLNode id = onlyChild(node); + Path path = (Path) getValue(id); + + FieldMetaData fld = path.last(); + + if (fld != null) { + // validate the field is of type java.util.Map + if (fld.getDeclaredTypeCode() != JavaTypes.MAP) { + String oper = "VALUE"; + if (node.id == JJTENTRY) + oper = "ENTRY"; + else if (node.id == JJTKEY) + oper = "KEY"; + throw parseException(EX_USER, "bad-qualified-identifier", + new Object[]{ id.text, oper}, null); + } + } + + if (node.id == JJTVALUE) + return path; + + Value value = getValue(id); + if (node.id == JJTKEY) + return factory.mapKey(path, value); + else + return factory.mapEntry(path, value); + } + private Value getTypeLiteral(JPQLNode node) { JPQLNode type = onlyChild(node); final String name = type.text; @@ -1460,7 +1501,7 @@ /** * Process type_discriminator * type_discriminator ::= - * TYPE(identification_variable | + * TYPE(general_identification_variable | * single_valued_object_path_expression | * input_parameter ) */ @@ -1475,6 +1516,9 @@ case JJTPOSITIONALINPUTPARAMETER: return factory.type(getParameter(node.text, true, false)); + case JJTGENERALIDENTIFIER: + return factory.type(getQualifiedIdentifier(onlyChild(node))); + default: // TODO: enforce jpa2.0 spec rules. // A single_valued_object_field is designated by the name of Modified: openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties?rev=750517&r1=750516&r2=750517&view=diff ============================================================================== --- openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties (original) +++ openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties Thu Mar 5 17:30:20 2009 @@ -73,3 +73,5 @@ jpql-parse-error: "{1}" while parsing JPQL "{0}". See nested stack trace for \ original parse error. not-type-literal: The specified node ("{0}") is not a valid entity type literal. +bad-qualified-identifier: The identifier "{0}" in "{1}" operator is not \ + referring to an association field of type java.util.Map. Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Division.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Division.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Division.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Division.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,61 @@ +/* + * 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.jdbc.maps.m2mmapex0; + +import javax.persistence.*; + +@Entity +@Table(name="m2mDivision") +public class Division { + @Id + int id; + + String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object o) { + Division d = (Division) o; + if (d.name.equals(name) && + d.getId() == id) + return true; + return false; + } + + public int hashCode() { + int ret = 0; + ret = ret * 31 + name.hashCode(); + ret = ret *31 + id; + return ret; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Employee.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Employee.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Employee.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/Employee.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,71 @@ +/* + * 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.jdbc.maps.m2mmapex0; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="m2mEmp") +public class Employee { + @Id + int empId; + + @ManyToMany // Bidirectional + Map phones = + new HashMap(); + + public Map getPhoneNumbers() { + return phones; + } + + public void addPhoneNumber(Division d, PhoneNumber phoneNumber) { + phones.put(d, phoneNumber); + } + + public void removePhoneNumber(Division d) { + phones.remove(d); + } + + public int getEmpId() { + return empId; + } + + public void setEmpId(int empId) { + this.empId = empId; + } + + public boolean equals(Object o) { + Employee e = (Employee) o; + Map map = e.getPhoneNumbers(); + if (map.size() != phones.size()) + return false; + Collection> entries = + (Collection>) phones.entrySet(); + for (Map.Entry entry : entries) { + Division key = entry.getKey(); + PhoneNumber p = entry.getValue(); + PhoneNumber p0 = map.get(key); + if (p.getNumber() != p0.getNumber()) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/PhoneNumber.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/PhoneNumber.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/PhoneNumber.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/PhoneNumber.java Thu Mar 5 17:30:20 2009 @@ -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.persistence.jdbc.maps.m2mmapex0; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="m2mPhone") +public class PhoneNumber { + @Id + int number; + + @ManyToMany(mappedBy = "phones") + Map emps = new HashMap(); + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public Map getEmployees() { + return emps; + } + + public void addEmployees(Division d, Employee employee) { + emps.put(d, employee); + } + + public void removeEmployee(Division d) { + emps.remove(d); + } + + public boolean equals(Object o) { + PhoneNumber p = (PhoneNumber) o; + Map map = p.getEmployees(); + if (map.size() != emps.size()) + return false; + Collection> entries = + (Collection>) emps.entrySet(); + for (Map.Entry entry : entries) { + Division key = entry.getKey(); + Employee e = entry.getValue(); + Employee e0 = map.get(key); + if (e.getEmpId() != e0.getEmpId()) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/TestMany2ManyMap.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/TestMany2ManyMap.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/TestMany2ManyMap.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex0/TestMany2ManyMap.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,258 @@ +/* + * 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.jdbc.maps.m2mmapex0; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.Query; + +import junit.framework.Assert; + +import org.apache.openjpa.lib.jdbc.AbstractJDBCListener; +import org.apache.openjpa.lib.jdbc.JDBCEvent; +import org.apache.openjpa.lib.jdbc.JDBCListener; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + + +public class TestMany2ManyMap extends SingleEMFTestCase { + + public int numEmployees = 2; + public int numPhoneNumbersPerEmployee = 2; + public Map empMap = new HashMap(); + public Map phoneMap = + new HashMap(); + + public List namedQueries = new ArrayList(); + + public int empId = 1; + public int phoneId = 1; + public int divId = 1; + + protected List sql = new ArrayList(); + protected int sqlCount; + + public void setUp() { + super.setUp(CLEAR_TABLES, Division.class, + Employee.class, PhoneNumber.class, + "openjpa.jdbc.JDBCListeners", + new JDBCListener[] { this.new Listener() }); + createObj(); + } + + public void testQueryQualifiedId() throws Exception { + EntityManager em = emf.createEntityManager(); + + String query = "select KEY(e) from PhoneNumber p, " + + " in (p.emps) e order by e.empId"; + List rs = em.createQuery(query).getResultList(); + Division d = (Division) rs.get(0); + + String query2 = "select KEY(p) from Employee e, " + + " in (e.phones) p"; + List rs2 = em.createQuery(query2).getResultList(); + Division d2 = (Division) rs2.get(0); + + String query3 = "select VALUE(e) from PhoneNumber p, " + + " in (p.emps) e"; + + List rs3 = em.createQuery(query3).getResultList(); + Employee e = (Employee) rs3.get(0); + + em.clear(); + String query4 = "select ENTRY(e) from PhoneNumber p, " + + " in (p.emps) e order by e.empId"; + List rs4 = em.createQuery(query4).getResultList(); + Map.Entry me = (Map.Entry) rs4.get(0); + + assertTrue(d.equals(me.getKey())); + + String query5 = "select TYPE(KEY(p)) from Employee e, " + + " in (e.phones) p"; + List rs5 = em.createQuery(query5).getResultList(); + assertEquals(Division.class, rs5.get(0)); + + em.close(); + } + + public void testQueryObject() throws Exception { + queryObj(); + findObj(); + } + + public List getSql() { + return sql; + } + + public int getSqlCount() { + return sqlCount; + } + + public void createObj() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + for (int i = 0; i < numEmployees; i++) { + Employee e = createEmployee(em, empId++); + empMap.put(e.getEmpId(), e); + } + tran.begin(); + em.flush(); + tran.commit(); + em.close(); + } + + public Employee createEmployee(EntityManager em, int id) { + Employee e = new Employee(); + e.setEmpId(id); + for (int i = 0; i < numPhoneNumbersPerEmployee; i++) { + PhoneNumber phoneNumber = new PhoneNumber(); + phoneNumber.setNumber(phoneId++); + Division d1 = createDivision(em, divId++); + Division d2 = createDivision(em, divId++); + phoneNumber.addEmployees(d1, e); + e.addPhoneNumber(d2, phoneNumber); + em.persist(phoneNumber); + phoneMap.put(phoneNumber.getNumber(), phoneNumber); + em.persist(d1); + em.persist(d2); + } + em.persist(e); + return e; + } + + public Division createDivision(EntityManager em, int id) { + Division d = new Division(); + d.setId(id); + d.setName("d" + id); + return d; + } + + public void removeAll() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + Query q = em.createNativeQuery("delete from department"); + q.executeUpdate(); + q = em.createNativeQuery("delete from employee"); + q.executeUpdate(); + System.out.println("committing removes"); + tran.commit(); + em.close(); + } + + public void findObj() throws Exception { + EntityManager em = emf.createEntityManager(); + Employee e = em.find(Employee.class, 1); + assertEmployee(e); + + PhoneNumber p = em.find(PhoneNumber.class, 1); + assertPhoneNumber(p); + em.close(); + } + + public void queryObj() throws Exception { + queryEmployee(); + queryPhoneNumber(); + } + + public void queryPhoneNumber() throws Exception { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + Query q = em.createQuery("select p from PhoneNumber p"); + List ps = q.getResultList(); + for (PhoneNumber p : ps) { + assertPhoneNumber(p); + } + tran.commit(); + em.close(); + } + + public void queryEmployee() throws Exception { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + Query q = em.createQuery("select e from Employee e"); + List es = q.getResultList(); + for (Employee e : es) { + assertEmployee(e); + } + tran.commit(); + em.close(); + } + + public void assertEmployee(Employee e) throws Exception { + int id = e.getEmpId(); + Employee e0 = empMap.get(id); + Map phones0 = e0.getPhoneNumbers(); + Map phones = e.getPhoneNumbers(); + Assert.assertEquals(phones0.size(), phones.size()); + checkPhoneMap(phones0, phones); + } + + public void assertPhoneNumber(PhoneNumber p) throws Exception { + int number = p.getNumber(); + PhoneNumber p0 = phoneMap.get(number); + Map es0 = p0.getEmployees(); + Map es = p.getEmployees(); + Assert.assertEquals(es0.size(), es.size()); + checkEmpMap(es0, es); + } + + public void checkPhoneMap(Map es0, + Map es) throws Exception { + Collection> entrySets0 = + es0.entrySet(); + for (Map.Entry entry0 : entrySets0) { + Division d0 = entry0.getKey(); + PhoneNumber p0 = entry0.getValue(); + PhoneNumber p = es.get(d0); + if (!p0.equals(p)) + throw new Exception("Assertion failure"); + } + } + + public void checkEmpMap(Map es0, + Map es) throws Exception { + Collection> entrySets0 = + es0.entrySet(); + for (Map.Entry entry0 : entrySets0) { + Division d0 = entry0.getKey(); + Employee e0 = entry0.getValue(); + Employee e = es.get(d0); + if (!e0.equals(e)) + throw new Exception("Assertion failure"); + } + } + + public class Listener extends AbstractJDBCListener { + @Override + public void beforeExecuteStatement(JDBCEvent event) { + if (event.getSQL() != null && sql != null) { + sql.add(event.getSQL()); + sqlCount++; + } + } + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Department.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Department.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Department.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Department.java Thu Mar 5 17:30:20 2009 @@ -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.jdbc.maps.m2mmapex1; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="MEx1Dept") +public class Department { + @Id + int id; + + String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object o) { + if (!(o instanceof Department)) + return false; + Department other = (Department) o; + if (name.equals(other.name) && + id == other.id) + return true; + return false; + } + + public int hashCode() { + int ret = 0; + ret = ret * 31 + name.hashCode(); + ret = ret *31 + id; + return ret; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Division.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Division.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Division.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Division.java Thu Mar 5 17:30:20 2009 @@ -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.jdbc.maps.m2mmapex1; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="MEx1Division") +public class Division { + @Id + int id; + + String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean equals(Object o) { + if (!(o instanceof Division)) + return false; + Division other = (Division) o; + if (name.equals(other.name) && + id == other.id) + return true; + return false; + } + + public int hashCode() { + int ret = 0; + ret = ret * 31 + name.hashCode(); + ret = ret *31 + id; + return ret; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Employee.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Employee.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Employee.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/Employee.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,71 @@ +/* + * 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.jdbc.maps.m2mmapex1; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="MEx1Emp") +public class Employee { + @Id + int empId; + + @ManyToMany + Map phones = + new HashMap(); + + public Map getPhoneNumbers() { + return phones; + } + + public void addPhoneNumber(Department d, PhoneNumber phoneNumber) { + phones.put(d, phoneNumber); + } + + public void removePhoneNumber(Department d) { + phones.remove(d); + } + + public int getEmpId() { + return empId; + } + + public void setEmpId(int empId) { + this.empId = empId; + } + + public boolean equals(Object o) { + Employee e = (Employee) o; + Map map = e.getPhoneNumbers(); + if (map.size() != phones.size()) + return false; + Collection> entries = + (Collection>) phones.entrySet(); + for (Map.Entry entry : entries) { + Department key = entry.getKey(); + PhoneNumber p = entry.getValue(); + PhoneNumber p0 = map.get(key); + if (p.getNumber() != p0.getNumber()) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/PhoneNumber.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/PhoneNumber.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/PhoneNumber.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/PhoneNumber.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,69 @@ +/* + * 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.jdbc.maps.m2mmapex1; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="MEx1Phone") +public class PhoneNumber { + @Id int number; + + @ManyToMany(mappedBy="phones") + Map emps = new HashMap(); + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public Map getEmployees() { + return emps; + } + + public void addEmployees(Division d, Employee employee) { + emps.put(d, employee); + } + + public void removeEmployee(Division d) { + emps.remove(d); + } + + public boolean equals(Object o) { + PhoneNumber p = (PhoneNumber) o; + Map map = p.getEmployees(); + if (map.size() != emps.size()) + return false; + Collection> entries = + (Collection>) emps.entrySet(); + for (Map.Entry entry : entries) { + Division key = entry.getKey(); + Employee e = entry.getValue(); + Employee e0 = map.get(key); + if (e.getEmpId() != e0.getEmpId()) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/TestMany2ManyMapEx1.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/TestMany2ManyMapEx1.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/TestMany2ManyMapEx1.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex1/TestMany2ManyMapEx1.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,248 @@ +/* + * 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.jdbc.maps.m2mmapex1; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Query; + +import junit.framework.Assert; + +import org.apache.openjpa.lib.jdbc.AbstractJDBCListener; +import org.apache.openjpa.lib.jdbc.JDBCEvent; +import org.apache.openjpa.lib.jdbc.JDBCListener; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestMany2ManyMapEx1 extends SingleEMFTestCase { + + public int numEmployees = 2; + public int numPhoneNumbersPerEmployee = 2; + + public Map empMap = new HashMap(); + public Map phoneMap = + new HashMap(); + + public List namedQueries = new ArrayList(); + + public int empId = 1; + public int phoneId = 1; + public int divId = 1; + public int deptId = 10; + + protected List sql = new ArrayList(); + protected int sqlCount; + + public void setUp() { + super.setUp(CLEAR_TABLES, + Department.class, + Division.class, + Employee.class, + PhoneNumber.class, + "openjpa.jdbc.JDBCListeners", + new JDBCListener[] { + this.new Listener() + }); + + createObj(emf); + } + + public void testQueryQualifiedId() throws Exception { + EntityManager em = emf.createEntityManager(); + String query = "select KEY(e), p from PhoneNumber p, " + + " in (p.emps) e order by e.empId"; + List rs = em.createQuery(query).getResultList(); + Division d = (Division) ((Object[]) rs.get(0))[0]; + PhoneNumber p = (PhoneNumber) ((Object[]) rs.get(0))[1]; + + String query2 = "select KEY(p) from Employee e, " + + " in (e.phones) p"; + List rs2 = em.createQuery(query2).getResultList(); + Department d2 = (Department) rs2.get(0); + + em.clear(); + String query4 = "select ENTRY(e) from PhoneNumber p, " + + " in (p.emps) e order by e.empId"; + List rs4 = em.createQuery(query4).getResultList(); + Map.Entry me = (Map.Entry) rs4.get(0); + + assertTrue(d.equals(me.getKey())); + + em.close(); + } + + public void testQueryObject() throws Exception { + queryObj(emf); + findObj(emf); + } + + public List getSql() { + return sql; + } + + public int getSqlCount() { + return sqlCount; + } + + public void createObj(EntityManagerFactory emf) { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + for (int i = 0; i < numEmployees; i++) { + Employee e = createEmployee(em, empId++); + empMap.put(e.getEmpId(), e); + } + tran.begin(); + em.flush(); + tran.commit(); + em.close(); + } + + public Employee createEmployee(EntityManager em, int id) { + Employee e = new Employee(); + e.setEmpId(id); + for (int i = 0; i < numPhoneNumbersPerEmployee; i++) { + PhoneNumber phoneNumber = new PhoneNumber(); + phoneNumber.setNumber(phoneId++); + Division div = createDivision(em, divId++); + Department dept = createDepartment(em, deptId++); + phoneNumber.addEmployees(div, e); + e.addPhoneNumber(dept, phoneNumber); + phoneMap.put(phoneNumber.getNumber(), phoneNumber); + em.persist(phoneNumber); + em.persist(dept); + em.persist(div); + } + em.persist(e); + return e; + } + + public Division createDivision(EntityManager em, int id) { + Division d = new Division(); + d.setId(id); + d.setName("d" + id); + return d; + } + + public Department createDepartment(EntityManager em, int id) { + Department d = new Department(); + d.setId(id); + d.setName("dept" + id); + return d; + } + + public void findObj(EntityManagerFactory emf) throws Exception { + EntityManager em = emf.createEntityManager(); + Employee e = em.find(Employee.class, 1); + assertEmployee(e); + + PhoneNumber p = em.find(PhoneNumber.class, 1); + assertPhoneNumber(p); + em.close(); + } + + public void queryObj(EntityManagerFactory emf) throws Exception { + queryEmployee(emf); + queryPhoneNumber(emf); + } + + public void queryPhoneNumber(EntityManagerFactory emf) throws Exception { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + Query q = em.createQuery("select p from PhoneNumber p"); + List ps = q.getResultList(); + for (PhoneNumber p : ps) { + assertPhoneNumber(p); + } + tran.commit(); + em.close(); + } + + public void queryEmployee(EntityManagerFactory emf) throws Exception { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + Query q = em.createQuery("select e from Employee e"); + List es = q.getResultList(); + for (Employee e : es) { + assertEmployee(e); + } + tran.commit(); + em.close(); + } + + public void assertEmployee(Employee e) throws Exception { + int id = e.getEmpId(); + Employee e0 = empMap.get(id); + Map phones0 = e0.getPhoneNumbers(); + Map phones = e.getPhoneNumbers(); + Assert.assertEquals(phones0.size(), phones.size()); + checkPhoneMap(phones0, phones); + } + + public void assertPhoneNumber(PhoneNumber p) throws Exception { + int number = p.getNumber(); + PhoneNumber p0 = phoneMap.get(number); + Map es0 = p0.getEmployees(); + Map es = p.getEmployees(); + Assert.assertEquals(es0.size(), es.size()); + checkEmpMap(es0, es); + } + + public void checkPhoneMap(Map es0, + Map es) throws Exception { + Collection> entrySets0 = + es0.entrySet(); + for (Map.Entry entry0 : entrySets0) { + Department d0 = entry0.getKey(); + PhoneNumber p0 = entry0.getValue(); + PhoneNumber p = es.get(d0); + if (!p0.equals(p)) + throw new Exception("Assertion failure"); + } + } + + public void checkEmpMap(Map es0, + Map es) throws Exception { + Collection> entrySets0 = es0.entrySet(); + for (Map.Entry entry0 : entrySets0) { + Division d0 = entry0.getKey(); + Employee e0 = entry0.getValue(); + Employee e = es.get(d0); + if (!e0.equals(e)) + throw new Exception("Assertion failure"); + } + } + + public class Listener extends AbstractJDBCListener { + @Override + public void beforeExecuteStatement(JDBCEvent event) { + if (event.getSQL() != null && sql != null) { + sql.add(event.getSQL()); + sqlCount++; + } + } + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/Employee.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/Employee.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/Employee.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/Employee.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,81 @@ +/* + * 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.jdbc.maps.m2mmapex10; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="MEx10Emp") +public class Employee { + @EmbeddedId + EmployeePK empPK; + + @ManyToMany // Bidirectional + Map phones = new HashMap(); + + int salary; + + public EmployeePK getEmpPK() { + return empPK; + } + + public void setEmpPK(EmployeePK empPK) { + this.empPK = empPK; + } + + + public Map getPhoneNumbers() { + return phones; + } + + public void addPhoneNumber(PhonePK d, PhoneNumber phoneNumber) { + phones.put(d, phoneNumber); + } + + public void removePhoneNumber(PhonePK d) { + phones.remove(d); + } + + public int getSalary() { + return salary; + } + + public void setSalary(int salary) { + this.salary = salary; + } + + public boolean equals(Object o) { + Employee e = (Employee) o; + Map map = e.getPhoneNumbers(); + if (map.size() != phones.size()) + return false; + Collection> entries = + (Collection>) phones.entrySet(); + for (Map.Entry entry : entries) { + PhonePK key = entry.getKey(); + PhoneNumber p = entry.getValue(); + PhoneNumber p0 = map.get(key); + if (!p.getPhonePK().equals(p0.getPhonePK())) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/EmployeePK.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/EmployeePK.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/EmployeePK.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/EmployeePK.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,55 @@ +/* + * 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.jdbc.maps.m2mmapex10; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.*; + +@Embeddable +public class EmployeePK implements Serializable { + String name; + Date bDay; + + public EmployeePK() {} + public EmployeePK(String name, Date bDay) { + this.name = name; + this.bDay = bDay; + } + + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof EmployeePK)) + return false; + EmployeePK pk = (EmployeePK) o; + if (pk.name.equals(name) && + pk.bDay.equals(bDay)) + return true; + return false; + } + + public int hashCode() { + int code = 0; + code += name.hashCode(); + code += bDay.hashCode(); + return code; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhoneNumber.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhoneNumber.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhoneNumber.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhoneNumber.java Thu Mar 5 17:30:20 2009 @@ -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.persistence.jdbc.maps.m2mmapex10; + +import javax.persistence.*; + +import java.util.*; + +@Entity +@Table(name="MEx10Phone") +public class PhoneNumber { + @EmbeddedId + PhonePK phonePK; + + @ManyToMany(mappedBy="phones") + Map emps = new HashMap(); + + int room; + + public PhonePK getPhonePK() { + return phonePK; + } + + public void setPhonePK(PhonePK phonePK) { + this.phonePK = phonePK; + } + + public Map getEmployees() { + return emps; + } + + public void addEmployees(EmployeePK d, Employee employee) { + emps.put(d, employee); + } + + public void removeEmployee(EmployeePK d) { + emps.remove(d); + } + + public int getRoom() { + return room; + } + + public void setRoom(int room) { + this.room = room; + } + + public boolean equals(Object o) { + PhoneNumber p = (PhoneNumber) o; + Map map = p.getEmployees(); + if (map.size() != emps.size()) + return false; + Collection> entries = + (Collection>) emps.entrySet(); + for (Map.Entry entry : entries) { + EmployeePK key = entry.getKey(); + Employee e0 = map.get(key); + Employee e = emps.get(key); + if (!e.getEmpPK().equals(e0.getEmpPK())) + return false; + } + return true; + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhonePK.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhonePK.java?rev=750517&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhonePK.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/PhonePK.java Thu Mar 5 17:30:20 2009 @@ -0,0 +1,54 @@ +/* + * 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.jdbc.maps.m2mmapex10; + +import java.io.Serializable; + +import javax.persistence.*; + +@Embeddable +public class PhonePK implements Serializable { + String areaCode; + String phoneNum; + + public PhonePK() {} + public PhonePK(String areaCode, String phoneNum) { + this.areaCode = areaCode; + this.phoneNum = phoneNum; + } + + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof PhonePK)) + return false; + PhonePK pk = (PhonePK) o; + if (pk.areaCode.equals(areaCode) && + pk.phoneNum.equals(phoneNum)) + return true; + return false; + } + + public int hashCode() { + int code = 0; + code = code * 31 + areaCode.hashCode(); + code = code * 31 + phoneNum.hashCode(); + return code; + } +}