From 4c4219fc223dcfcaee24119825d5b63f31c2dc67 Mon Sep 17 00:00:00 2001 From: Pinaki Poddar Date: Fri, 5 Dec 2008 01:37:13 +0000 Subject: [PATCH] OPENJPA-806: Initial Criteria API implementation. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@723553 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/persistence/criteria/Address.java | 39 ++ .../openjpa/persistence/criteria/Contact.java | 26 + .../persistence/criteria/Contractor.java | 26 + .../openjpa/persistence/criteria/Course.java | 26 + .../persistence/criteria/CreditCard.java | 26 + .../persistence/criteria/Customer.java | 27 + .../persistence/criteria/Department.java | 32 ++ .../persistence/criteria/Employee.java | 26 + .../openjpa/persistence/criteria/Exempt.java | 26 + .../openjpa/persistence/criteria/Item.java | 26 + .../openjpa/persistence/criteria/Manager.java | 26 + .../openjpa/persistence/criteria/Order.java | 33 ++ .../openjpa/persistence/criteria/Person.java | 26 + .../openjpa/persistence/criteria/Phone.java | 26 + .../criteria/StringComparison.java | 121 +++++ .../persistence/criteria/TestCriteria.java | 413 +++++++++++++++ .../persistence/criteria/VideoStore.java | 26 + .../persistence/EntityManagerFactoryImpl.java | 4 +- .../persistence/query/AbsExpression.java | 31 ++ .../query/AbstractDomainObject.java | 395 +++++++++++++++ .../persistence/query/AbstractPath.java | 124 +++++ .../persistence/query/AliasContext.java | 60 +++ .../persistence/query/AllExpression.java | 35 ++ .../persistence/query/AndPredicate.java | 34 ++ .../persistence/query/AnyExpression.java | 34 ++ .../persistence/query/AverageExpression.java | 31 ++ .../persistence/query/BetweenExpression.java | 39 ++ .../query/BinaryConditionalOperator.java | 55 ++ .../query/BinaryExpressionPredicate.java | 75 +++ .../query/BinaryFunctionalOperator.java | 50 ++ .../query/BinaryOperatorExpression.java | 62 +++ .../persistence/query/CaseExpressionImpl.java | 197 ++++++++ .../query/ConditionalOperator.java | 31 ++ .../persistence/query/ConstantExpression.java | 60 +++ .../persistence/query/CountExpression.java | 33 ++ .../query/CurrentTimeExpression.java | 56 ++ .../persistence/query/DistinctExpression.java | 35 ++ .../query/DividedByExpression.java | 33 ++ .../persistence/query/ElseExpression.java | 63 +++ .../persistence/query/EntryExpression.java | 31 ++ .../persistence/query/EqualExpression.java | 34 ++ .../persistence/query/ExistsExpression.java | 32 ++ .../persistence/query/ExpressionImpl.java | 477 ++++++++++++++++++ .../openjpa/persistence/query/FetchPath.java | 42 ++ .../query/GreaterEqualExpression.java | 34 ++ .../query/GreaterThanExpression.java | 34 ++ .../persistence/query/InExpression.java | 15 + .../persistence/query/IndexExpression.java | 34 ++ .../persistence/query/IsEmptyExpression.java | 16 + .../persistence/query/IsNullExpression.java | 39 ++ .../openjpa/persistence/query/JPQLHelper.java | 33 ++ .../openjpa/persistence/query/JoinPath.java | 78 +++ .../persistence/query/KeyExpression.java | 31 ++ .../persistence/query/LengthExpression.java | 33 ++ .../query/LessEqualExpression.java | 34 ++ .../persistence/query/LessThanExpression.java | 35 ++ .../persistence/query/LikeExpression.java | 44 ++ .../persistence/query/LiteralExpression.java | 31 ++ .../persistence/query/LocateExpression.java | 33 ++ .../persistence/query/LogicalPredicate.java | 59 +++ .../persistence/query/LowerExpression.java | 33 ++ .../persistence/query/MaxExpression.java | 33 ++ .../persistence/query/MemberOfExpression.java | 34 ++ .../persistence/query/MinExpression.java | 33 ++ .../persistence/query/MinusExpression.java | 33 ++ .../persistence/query/ModExpression.java | 37 ++ .../persistence/query/NavigationPath.java | 62 +++ .../persistence/query/NewInstance.java | 70 +++ .../persistence/query/NotEqualExpression.java | 35 ++ .../persistence/query/OperatorPath.java | 58 +++ .../persistence/query/OrPredicate.java | 35 ++ .../persistence/query/OrderableItem.java | 47 ++ .../query/ParameterExpression.java | 36 ++ .../persistence/query/PathOperator.java | 48 ++ .../persistence/query/PlusExpression.java | 33 ++ .../persistence/query/QueryBuilderImpl.java | 55 ++ .../query/QueryDefinitionImpl.java | 425 ++++++++++++++++ .../persistence/query/QueryExpression.java | 41 ++ .../persistence/query/RangeExpression.java | 39 ++ .../openjpa/persistence/query/RootPath.java | 41 ++ .../openjpa/persistence/query/Selectable.java | 32 ++ .../persistence/query/SizeExpression.java | 33 ++ .../persistence/query/SomeExpression.java | 33 ++ .../query/SquareRootExpression.java | 33 ++ .../query/SubStringExpression.java | 45 ++ .../persistence/query/SumExpression.java | 33 ++ .../persistence/query/TimesExpression.java | 33 ++ .../persistence/query/ToUpperExpression.java | 33 ++ .../persistence/query/TrimExpression.java | 41 ++ .../persistence/query/TypeExpression.java | 33 ++ .../query/UnaryConditionalOperator.java | 49 ++ .../query/UnaryExpressionPredicate.java | 67 +++ .../query/UnaryFunctionalOperator.java | 61 +++ .../query/UnaryMinusExpression.java | 35 ++ .../persistence/query/UnaryOperator.java | 65 +++ .../query/UnaryOperatorExpression.java | 52 ++ .../persistence/query/ValueExpression.java | 31 ++ .../openjpa/persistence/query/Visitable.java | 33 ++ .../openjpa/persistence/query/WhenClause.java | 55 ++ 99 files changed, 5710 insertions(+), 2 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contact.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contractor.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Course.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CreditCard.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Customer.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Department.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Employee.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Exempt.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Item.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Manager.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Person.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Phone.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/StringComparison.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/VideoStore.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbsExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AllExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AndPredicate.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AnyExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AverageExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BetweenExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryConditionalOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryExpressionPredicate.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryFunctionalOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryOperatorExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CaseExpressionImpl.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConditionalOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConstantExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CountExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CurrentTimeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DistinctExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DividedByExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ElseExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EntryExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EqualExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExistsExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterEqualExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterThanExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/InExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IndexExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsEmptyExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsNullExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JPQLHelper.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/KeyExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LengthExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessEqualExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessThanExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LikeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LiteralExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LocateExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LogicalPredicate.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LowerExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MaxExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MemberOfExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinusExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ModExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NewInstance.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NotEqualExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrPredicate.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrderableItem.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ParameterExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PathOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PlusExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RangeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Selectable.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SizeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SomeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SquareRootExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SubStringExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SumExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TimesExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ToUpperExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TrimExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TypeExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryConditionalOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryExpressionPredicate.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryFunctionalOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryMinusExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperator.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperatorExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ValueExpression.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/WhenClause.java diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java new file mode 100644 index 000000000..b1d969d5a --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java @@ -0,0 +1,39 @@ +/* + * 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.criteria; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.OneToMany; + +/** + * Used for testing Criteria API. + * The fields are sometimes not declared as there is no validation yet during + * Query construction. + * + * @author Pinaki Poddar + * + */ +@Entity +public class Address { + private String zipCode; + @OneToMany + private List phones; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contact.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contact.java new file mode 100644 index 000000000..1d6f80937 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contact.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.OneToOne; + +public class Contact { + @OneToOne + private Address address; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contractor.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contractor.java new file mode 100644 index 000000000..a3a259281 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Contractor.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Contractor { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Course.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Course.java new file mode 100644 index 000000000..589ce73d7 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Course.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Course { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CreditCard.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CreditCard.java new file mode 100644 index 000000000..78609c60d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CreditCard.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class CreditCard { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Customer.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Customer.java new file mode 100644 index 000000000..4a2df9556 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Customer.java @@ -0,0 +1,27 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Customer { + private String firstName; + private String lastName; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Department.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Department.java new file mode 100644 index 000000000..e45b4aa01 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Department.java @@ -0,0 +1,32 @@ +/* + * 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.criteria; + +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.OneToMany; + +@Entity +public class Department { + private int deptNo; + private String name; + @OneToMany + private Set employees; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Employee.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Employee.java new file mode 100644 index 000000000..dad98ac28 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Employee.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Employee { + private Address contactInfo; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Exempt.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Exempt.java new file mode 100644 index 000000000..63ccfe53d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Exempt.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Exempt { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Item.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Item.java new file mode 100644 index 000000000..b6ccfb894 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Item.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Item { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Manager.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Manager.java new file mode 100644 index 000000000..99cf404f5 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Manager.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Manager { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java new file mode 100644 index 000000000..2d76301f2 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java @@ -0,0 +1,33 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name="C_ORDER") +public class Order { + private int quantity; + + @ManyToOne + private Customer customer; + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Person.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Person.java new file mode 100644 index 000000000..3fd1e6ab8 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Person.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Person { + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Phone.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Phone.java new file mode 100644 index 000000000..1f9e106b4 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Phone.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class Phone { + private String vendor; +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/StringComparison.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/StringComparison.java new file mode 100644 index 000000000..6061b6516 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/StringComparison.java @@ -0,0 +1,121 @@ +/* + * 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.criteria; + +import java.io.IOException; +import java.io.StreamTokenizer; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Compares a pair of String ignoring case-sensitivity of set of reserved words. + * + * @author Pinaki Poddar + * + */ +public class StringComparison { + private static List _reserved = Arrays.asList(new String[] { + "ALL", "AND", "ANY", "AS", "ASC", "AVG", + "BETWEEN", "BIT_LENGTH", "BY", + "CASE", "CHAR_LENGTH", "CHARACTER_LENGTH", "CLASS", "COALESCE", + "COUNT","CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "DELETE", "DESC", "DISTINCT", + "EMPTY", "ENTRY", "EXISTS", + "FALSE", "FETCH", "FROM", + "GROUP", + "HAVING", + "IN", "INDEX", "INNER", "IS", + "JOIN", + "KEY", + "LEFT", "LIKE", "LOWER", + "MAX", "MEMBER", "MIN", "MOD", + "NEW", "NOT", "NULL", "NULLIF", + "OBJECT", "OF", "OR", "ORDER", "OUTER", + "POSITION", + "SELECT", "SOME", "SUM", + "THEN", "TRIM", "TRUE", "TYPE", + "UNKNOWN", "UPDATE", "UPPER", + "VALUE", + "WHEN", "WHERE", + }); + + private boolean isReservedWord(String s) { + return _reserved.contains(s.toUpperCase()); + } + + public List tokenize(String s) throws IOException { + List list = new ArrayList(); + StreamTokenizer tok = new StreamTokenizer(new StringReader(s)); + tok.resetSyntax(); + tok.wordChars('a', 'z'); + tok.wordChars('0', '9'); + tok.wordChars('A', 'Z'); + tok.wordChars('\'', '\''); + tok.wordChars('=', '='); + tok.wordChars('>', '>'); + tok.wordChars('<', '<'); + tok.wordChars('!', '!'); + tok.wordChars('.', '.'); + for (int ttype; (ttype = tok.nextToken()) != StreamTokenizer.TT_EOF;) { + if (ttype == StreamTokenizer.TT_WORD) + list.add(tok.sval); + } + return list; + } + + public boolean compare(String s1, String s2) { + try { + List list1 = tokenize(s1); + List list2 = tokenize(s2); + if (list1.size() != list2.size()) { + System.err.println("Unequal tokens " + list1.size() + "!=" + list2.size()); + return false; + } + for (int i = 0; i < list1.size(); i++) { + String a = list1.get(i); + String b = list2.get(i); + boolean match = isReservedWord(a) ? a.equalsIgnoreCase(b) : a.equals(b); + if (!match) { + System.err.println("[" + a + "] does not match [" + b + "]"); + return false; + } + } + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + public static void main(String[] args) throws Exception { + StringComparison c = new StringComparison(); + String s1 = "SELECT DISTINCT o FROM Order AS o JOIN o.lineItems AS l WHERE l.shipped != FALSE and l.name like 'hello'"; + String s2 = "select DISTINCT o FROM Order AS o JOIN o.lineItems AS l WHERE l.shipped != FALSE and l.name like 'hello'"; + boolean match = c.compare(s1, s2); + if (!match) { + System.err.println(s1); + System.err.println(c.tokenize(s1)); + System.err.println(s2); + System.err.println(c.tokenize(s2)); + } + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java new file mode 100644 index 000000000..0b656bd36 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestCriteria.java @@ -0,0 +1,413 @@ +/* + * 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.criteria; + +import javax.persistence.DomainObject; +import javax.persistence.QueryBuilder; +import javax.persistence.QueryDefinition; +import javax.persistence.SelectItem; + +import org.apache.openjpa.persistence.query.AbstractDomainObject; +import org.apache.openjpa.persistence.query.QueryDefinitionImpl; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + + +/** + * Tests by stringifying QueryDefinition and comparing the resultant string + * with an equivalent JPQL. + * + * Does not execute the query. + * + * The examples are taken from Criteria API Section of Java Persistence API + * Version 2.0 [1]. + * + * [1] + * JPA API Specification Version 2.0 + * + * @author Pinaki Poddar + * + */ +public class TestCriteria extends SingleEMFTestCase { + protected QueryBuilder qb; + protected StringComparison comparator = new StringComparison(); + + public void setUp() { + super.setUp(Contractor.class, Course.class, CreditCard.class, + Department.class, Employee.class, Exempt.class, Item.class, + Manager.class, Person.class, VideoStore.class, Order.class, + Customer.class); + qb = emf.getQueryBuilder(); + } + + public void tearDown() { + // do nothing as you do not have a database connection + } + + void compare(String s, QueryDefinition q) { + String actual = ((QueryDefinitionImpl)q).toJPQL(); + if (!comparator.compare(s,actual)) { + fail("\r\nExpected: [" + s + "]\r\nActual : [" + actual + "]"); + } + } + + void compare(String s, DomainObject q) { + String actual = ((AbstractDomainObject)q).getOwner().toJPQL(); + if (!comparator.compare(s,actual)) { + fail("\r\nExpected: [" + s + "]\r\nActual : [" + actual + "]"); + } + } + + public void testMultipleDomainOfSameClass() { + DomainObject o1 = qb.createQueryDefinition(Order.class); + DomainObject o2 = o1.addRoot(Order.class); + o1.select(o1) + .where(o1.get("quantity").greaterThan(o2.get("quantity")) + .and(o2.get("customer").get("lastName").equal("Smith")) + .and(o2.get("customer").get("firstName").equal("John"))); + + String jpql = "select o from Order o, Order o2" + + " where o.quantity > o2.quantity" + + " and o2.customer.lastName = 'Smith'" + + " and o2.customer.firstName = 'John'"; + compare(jpql, o1); + } + + public void testFetchJoin() { + DomainObject d = qb.createQueryDefinition(Department.class); + d.leftJoinFetch("employees"); + d.where(d.get("deptNo").equal(1)); + + + String jpql = "select d from Department d" + + " LEFT JOIN FETCH d.employees" + + " where d.deptNo = 1"; + compare(jpql, d); + } + + public void testMultipartNavigation() { + DomainObject e = qb.createQueryDefinition(Employee.class); + DomainObject p = e.join("contactInfo").join("phones"); + e.where(e.get("contactInfo").get("address").get("zipCode") + .equal("95094")).select(p.get("vendor")); + + + String jpql = "select p.vendor from Employee e" + + " JOIN e.contactInfo c JOIN c.phones p" + + " where e.contactInfo.address.zipCode = '95094'"; + compare(jpql, e); + } + + public void testOperatorPath() { + QueryDefinition qdef = qb.createQueryDefinition(); + DomainObject item = qdef.addRoot(Item.class); + DomainObject photo = item.join("photos"); + qdef.select(item.get("name"), photo.value()) + .where(photo.key().like("egret")); + + + String jpql = "select i.name, VALUE(p) from Item i join i.photos p where KEY(p) like 'egret'"; + compare(jpql, qdef); + } + + public void testLiteral() { + DomainObject c = qb.createQueryDefinition(Customer.class); + DomainObject o = c.join("orders"); + DomainObject a = c.join("address"); + o.where(a.get("state").equal("CA").and(a.get("county").equal("Santa Clara"))); + o.select(o.get("quantity"), o.get("cost").times(1.08), a.get("zipCode")); + + String jpql = "select o.quantity, o.cost*1.08, a.zipCode" + + " from Customer c join c.orders o join c.address a" + + " where a.state = 'CA' and a.county = 'Santa Clara'"; + compare(jpql, c); + } + + public void testTypeExpression() { + DomainObject e = qb.createQueryDefinition(Employee.class); + e.select(e.type()) + .where(e.type().equal(Exempt.class).not()); + + String jpql = "select TYPE(e)" + + " from Employee e" + + " where TYPE(e) <> Exempt"; + compare(jpql, e); + } + + public void testIndex() { + DomainObject c = qb.createQueryDefinition(Course.class); + DomainObject w = c.join("studentWaitList"); + c.where(c.get("name").equal("Calculus").and(w.index().equal(0))) + .select(w.get("name")); + + String jpql = "select s.name" + + " from Course c join c.studentWaitList s" + + " where c.name = 'Calculus' and INDEX(s) = 0"; + compare(jpql, c); + } + + public void testSum() { + DomainObject o = qb.createQueryDefinition(Order.class); + DomainObject l = o.join("lineItems"); + DomainObject c = o.join("customer"); + c.where(c.get("lastName").equal("Smith").and(c.get("firstName").equal("John"))) + .select(l.get("price").sum()); + + String jpql = "select SUM(l.price)" + + " from Order o join o.lineItems l JOIN o.customer c" + + " where c.lastName = 'Smith' and c.firstName = 'John'"; + compare(jpql, c); + } + + public void testSize() { + DomainObject d = qb.createQueryDefinition(Department.class); + d.where(d.get("name").equal("Sales")) + .select(d.get("employees").size()); + + String jpql = "select SIZE(d.employees)" + + " from Department d " + + " where d.name = 'Sales'"; + compare(jpql, d); + } + + public void testGeneralCase() { + DomainObject e = qb.createQueryDefinition(Employee.class); + e.where(e.get("department").get("name").equal("Engineering")); + e.select(e.get("name"), + e.generalCase() + .when(e.get("rating").equal(1)) + .then(e.get("salary").times(1.1)) + .when(e.get("rating").equal(2)) + .then(e.get("salary").times(1.2)) + .elseCase(e.get("salary").times(1.01))); + + String jpql = "SELECT e.name," + + " CASE WHEN e.rating = 1 THEN e.salary * 1.1" + + " WHEN e.rating = 2 THEN e.salary * 1.2" + + " ELSE e.salary * 1.01" + + " END" + + " FROM Employee e" + + " WHERE e.department.name = 'Engineering'"; + + compare(jpql, e); + } + + public void testMemberOf() { + DomainObject p = qb.createQueryDefinition(Person.class); + p.where(p.literal("Joe").member(p.get("nicknames"))); + + String jpql = "select p from Person p " + + " where 'Joe' MEMBER OF p.nicknames"; + compare(jpql, p); + } + + public void testParamater() { + QueryDefinition qdef = qb.createQueryDefinition(); + DomainObject customer = qdef.addRoot(Customer.class); + qdef.where(customer.get("status").equal(qdef.param("status"))); + + String jpql = "select c from Customer c " + + " where c.status = :status"; + compare(jpql, qdef); + } + + public void testBetween() { + DomainObject c = qb.createQueryDefinition(CreditCard.class); + DomainObject t = c.join("transactionHistory"); + c.select(t).where(c.get("holder").get("name").equal("John Doe") + .and(t.index().between(0, 9))); + + + String jpql = "select t from CreditCard c JOIN c.transactionHistory t" + + " where c.holder.name = 'John Doe' AND INDEX(t) " + + " BETWEEN 0 AND 9"; + compare(jpql, c); + } + + public void testIsEmpty() { + DomainObject o = qb.createQueryDefinition(Order.class); + o.where(o.get("lineItems").isEmpty()); + + + String jpql = "select o from Order o " + + " where o.lineItems IS EMPTY"; + compare(jpql, o); + } + + public void testNonCorrelatedSubQuery() { + QueryDefinition q1 = qb.createQueryDefinition(); + DomainObject goodCustomer = q1.addRoot(Customer.class); + + QueryDefinition q2 = qb.createQueryDefinition(); + DomainObject customer = q2.addRoot(Customer.class); + + q1.where(goodCustomer.get("balanceOwned") + .lessThan(q2.select(customer.get("balanceOwned").avg()))); + + String jpql = "select c from Customer c " + + " where c.balanceOwned < " + + "(select AVG(c2.balanceOwned) from Customer c2)"; + compare(jpql, q1); + } + + public void testNew() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject customer = q.addRoot(Customer.class); + DomainObject order = customer.join("orders"); + q.where(order.get("count").greaterThan(100)) + .select(q.newInstance(Customer.class, + customer.get("id"), + customer.get("status"), + order.get("count"))); + + + String jpql = "SELECT NEW org.apache.openjpa.persistence.criteria.Customer(c.id, c.status, o.count)" + + " FROM Customer c JOIN c.orders o" + + " WHERE o.count > 100"; + compare(jpql, q); + } + + public void testKeyValueOperatorPath() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject v = q.addRoot(VideoStore.class); + DomainObject i = v.join("videoInventory"); + q.where(v.get("location").get("zipcode").equal("94301") + .and(i.value().greaterThan(0))); + q.select(v.get("location").get("street"), + i.key().get("title"), + i.value()); + + String jpql = "SELECT v.location.street, KEY(v2).title, VALUE(v2)" + + " FROM VideoStore v JOIN v.videoInventory v2" + + " WHERE v.location.zipcode = '94301' AND VALUE(v2) > 0"; + compare(jpql, q); + } + + public void testGroupByHaving() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject customer = q.addRoot(Customer.class); + q.select(customer.get("status"), + customer.get("filledOrderCount").avg(), + customer.count()) + .groupBy(customer.get("status")) + .having(customer.get("status").in(1, 2)); + + String jpql = "SELECT c.status, AVG(c.filledOrderCount), COUNT(c)" + + " FROM Customer c" + + " GROUP BY c.status" + + " HAVING c.status IN (1, 2)"; + + compare(jpql, q); + } + + public void testGroupByHaving2() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject customer = q.addRoot(Customer.class); + q.select(customer.get("country"), + customer.count()) + .groupBy(customer.get("country")) + .having(customer.count().greaterThan(30)); + + String jpql = "SELECT c.country, COUNT(c)" + + " FROM Customer c" + + " GROUP BY c.country" + + " HAVING COUNT(c) > 30"; + compare(jpql, q); + } + + public void testOrderBy() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject customer = q.addRoot(Customer.class); + DomainObject order = customer.join("orders"); + DomainObject address = customer.join("address"); + q.where(address.get("state").equal("CA")) + .select(order) + .orderBy(order.get("quantity").desc(), order.get("totalcost")); + String jpql = "SELECT o" + + " FROM Customer c JOIN c.orders o JOIN c.address a" + + " WHERE a.state = 'CA'" + + " ORDER BY o.quantity DESC, o.totalcost"; + compare(jpql, q); + } + + public void testOrderBy2() { + QueryDefinition q = qb.createQueryDefinition(); + DomainObject customer = q.addRoot(Customer.class); + DomainObject order = customer.join("orders"); + DomainObject address = customer.join("address"); + q.where(address.get("state").equal("CA")) + .select(order.get("quantity"), address.get("zipcode")) + .orderBy(order.get("quantity"), address.get("zipcode")); + String jpql = "SELECT o.quantity, a.zipcode" + + " FROM Customer c JOIN c.orders o JOIN c.address a" + + " WHERE a.state = 'CA'" + + " ORDER BY o.quantity, a.zipcode"; + compare(jpql, q); + } + + public void testOrderByExpression() { + DomainObject o = qb.createQueryDefinition(Order.class); + DomainObject a = o.join("customer").join("address"); + SelectItem taxedCost = o.get("cost").times(1.08); + o.select(o.get("quantity"), taxedCost, a.get("zipcode")) + .where(a.get("state").equal("CA") + .and(a.get("county").equal("Santa Clara"))) + .orderBy(o.get("quantity"), taxedCost, a.get("zipcode")); + + String jpql = "SELECT o.quantity, o.cost*1.08, a.zipcode" + + " FROM Order o JOIN o.customer c JOIN c.address a" + + " WHERE a.state = 'CA' AND a.county = 'Santa Clara'" + + " ORDER BY o.quantity, o.cost*1.08, a.zipcode"; + + compare(jpql, o); + } + + public void testCorrelatedSubquery() { + QueryDefinition q1 = qb.createQueryDefinition(); + DomainObject emp = q1.addRoot(Employee.class); + + QueryDefinition q2 = qb.createQueryDefinition(); + DomainObject spouseEmp = q2.addRoot(Employee.class); + + q2.where(spouseEmp.equal(emp.get("spouse"))).select(spouseEmp); + q1.selectDistinct(emp).where(q2.exists()); + + String jpql = "SELECT DISTINCT e " + + " FROM Employee e" + + " WHERE EXISTS (" + + " SELECT e2 " + + " FROM Employee e2" + + " WHERE e2 = e.spouse)"; + + compare(jpql, q1); + } + + public void testCreateSubquery() { + DomainObject customer = qb.createQueryDefinition(Customer.class); + DomainObject order = qb.createSubqueryDefinition(customer.get("orders")); + customer.where(order.select(order.get("price").avg()).greaterThan(100)); + + String jpql = "SELECT c " + + " FROM Customer c" + + " WHERE (SELECT AVG(o.price) FROM c.orders o) > 100"; + + compare(jpql, customer); + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/VideoStore.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/VideoStore.java new file mode 100644 index 000000000..b440abbc2 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/VideoStore.java @@ -0,0 +1,26 @@ +/* + * 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.criteria; + +import javax.persistence.Entity; + +@Entity +public class VideoStore { + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java index a081ffc76..d21147e7e 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java @@ -46,6 +46,7 @@ import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.conf.Value; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Closeable; +import org.apache.openjpa.persistence.query.QueryBuilderImpl; import org.apache.openjpa.util.OpenJPAException; import serp.util.Strings; @@ -342,8 +343,7 @@ public class EntityManagerFactoryImpl } public QueryBuilder getQueryBuilder() { - throw new UnsupportedOperationException( - "JPA 2.0 - Method not yet implemented"); + return new QueryBuilderImpl(); } public Set getSupportedProperties() { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbsExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbsExpression.java new file mode 100644 index 000000000..48c37cee4 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbsExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes ABS() operation on a given expression. + * + * @author Pinaki Poddar + * + */ +public class AbsExpression extends UnaryOperatorExpression { + public AbsExpression(ExpressionImpl op) { + super(op, UnaryFunctionalOperator.ABS); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java new file mode 100644 index 000000000..5b2e9d2cb --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractDomainObject.java @@ -0,0 +1,395 @@ +/* + * 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.query; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.persistence.CaseExpression; +import javax.persistence.DomainObject; +import javax.persistence.Expression; +import javax.persistence.FetchJoinObject; +import javax.persistence.OrderByItem; +import javax.persistence.PathExpression; +import javax.persistence.Predicate; +import javax.persistence.QueryDefinition; +import javax.persistence.SelectItem; +import javax.persistence.Subquery; + +/** + * Domain Object is a path expression over which query is evaluated. + * Domain object acts as a proxy for a QueryDefinition via delegation. + * + * @author Pinaki Poddar + * + */ +public abstract class AbstractDomainObject extends AbstractPath + implements DomainObject { + private final QueryDefinitionImpl _owner; + private List _joins; + private List _fetchJoins; + + protected AbstractDomainObject(QueryDefinitionImpl owner, + AbstractPath parent, PathOperator op, Object part2) { + super(parent, op, part2); + _owner = owner; + } + + /** + * Gets the QueryDefinition that created this path. + * @return + */ + public QueryDefinitionImpl getOwner() { + return _owner; + } + + /** + * Gets the fetch joins associated with this path. Can be null. + */ + public List getFetchJoins() { + return _fetchJoins; + } + + /** + * Gets the joins associated with this path. Can be null. + */ + public List getJoins() { + return _joins; + } + + /** + * Adding a root adds a root domain to the owning query. + */ + public DomainObject addRoot(Class cls) { + return _owner.addRoot(cls); + } + + /** + * Adding a query root adds a subquery to the owning query. + */ + public DomainObject addSubqueryRoot(PathExpression path) { + return _owner.addSubqueryRoot(path); + } + + /** + * Derives a path from this path by navigating through the given field. + */ + public PathExpression get(String attr) { + return new NavigationPath(_owner, this, attr); + } + + /** + * Derives a path from this path by joining the given field. + * Also the joined path becomes a domain of the owning query. + */ + public DomainObject join(String attribute) { + return join(attribute, PathOperator.INNER); + } + + /** + * Derives a path from this path by outer joining the given field. + * Also the joined path becomes a domain of the owning query. + */ + public DomainObject leftJoin(String attribute) { + return join(attribute, PathOperator.OUTER); + } + + protected DomainObject join(String attr, PathOperator joinType) { + JoinPath join = new JoinPath(this, joinType, attr); + if (_joins == null) { + _joins = new ArrayList(); + } + _joins.add(join); + return join; + } + + /** + * Derives a path from this path by fetch joining the given field. + */ + public FetchJoinObject joinFetch(String attribute) { + return fetchJoin(attribute, PathOperator.FETCH_INNER); + } + + /** + * Derives a path from this path by fetch joining the given field. + */ + public FetchJoinObject leftJoinFetch(String attribute) { + return fetchJoin(attribute, PathOperator.FETCH_OUTER); + } + + private FetchJoinObject fetchJoin(String attr, PathOperator joinType) { + NavigationPath path = new NavigationPath(_owner, this, attr); + FetchPath join = new FetchPath(path, joinType); + if (_fetchJoins == null) { + _fetchJoins = new ArrayList(); + } + _fetchJoins.add(join); + return join; + } + + /** + * Derives by KEY() operation on this path. + */ + public PathExpression key() { + return new KeyExpression(this); + } + + /** + * Derives by ENTRY() operation on this path. + */ + public SelectItem entry() { + return new EntryExpression(this); + } + + /** + * Derives by INDEX() operation on this path. + */ + public Expression index() { + return new IndexExpression(this); + } + + /** + * Derives a path by VALUE() operation on this path. + */ + public PathExpression value() { + return new ValueExpression(this); + } + + /** + * Derives this path as ALL(subquery) to its owning query. + */ + public Subquery all() { + return _owner.all(); + } + + /** + * Adds this path as ANY(subquery) to its owning query. + */ + public Subquery any() { + return _owner.any(); + } + + /** + * Adds this path as SOME(subquery) to its owning query. + */ + public Subquery some() { + return _owner.some(); + } + + /** + * Adds this path as EXISTS(subquery) to its owning query. + */ + public Predicate exists() { + return _owner.exists(); + } + + public Expression coalesce(Expression... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(String... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(Date... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(Calendar... exp) { + throw new UnsupportedOperationException(); + } + + public Expression currentDate() { + return _owner.currentDate(); + } + + public Expression currentTime() { + return _owner.currentTime(); + } + + public Expression currentTimestamp() { + return _owner.currentTimestamp(); + } + + public CaseExpression generalCase() { + return _owner.generalCase(); + } + + public QueryDefinition groupBy(PathExpression... pathExprs) { + return _owner.groupBy(pathExprs); + } + + public QueryDefinition groupBy(List pathExprList) { + return _owner.groupBy(pathExprList); + } + + public QueryDefinition having(Predicate predicate) { + return _owner.having(predicate); + } + + public Expression literal(String s) { + return _owner.literal(s); + } + + public Expression literal(Number n) { + return _owner.literal(n); + } + + public Expression literal(boolean b) { + return _owner.literal(b); + } + + public Expression literal(Calendar c) { + return _owner.literal(c); + } + + public Expression literal(Date d) { + return _owner.literal(d); + } + + public Expression literal(char c) { + return _owner.literal(c); + } + + public Expression literal(Class cls) { + return _owner.literal(cls); + } + + public Expression literal(Enum e) { + return _owner.literal(e); + } + + public SelectItem newInstance(Class cls, SelectItem... args) { + return _owner.newInstance(cls, args); + } + + public Expression nullLiteral() { + return _owner.nullLiteral(); + } + + public Expression nullif(Expression exp1, Expression exp2) { + return _owner.nullif(exp1, exp2); + } + + public Expression nullif(Number arg1, Number arg2) { + return _owner.nullif(arg1, arg2); + } + + public Expression nullif(String arg1, String arg2) { + return _owner.nullif(arg1, arg2); + } + + public Expression nullif(Date arg1, Date arg2) { + return _owner.nullif(arg1, arg2); + } + + public Expression nullif(Calendar arg1, Calendar arg2) { + return _owner.nullif(arg1, arg2); + } + + public Expression nullif(Class arg1, Class arg2) { + return _owner.nullif(arg1, arg2); + } + + public Expression nullif(Enum arg1, Enum arg2) { + return _owner.nullif(arg1, arg2); + } + + public QueryDefinition orderBy(OrderByItem... orderByItems) { + return _owner.orderBy(orderByItems); + } + + public QueryDefinition orderBy(List orderByItemList) { + return _owner.orderBy(orderByItemList); + } + + public Expression param(String name) { + return _owner.param(name); + } + + public Predicate predicate(boolean b) { + return _owner.predicate(b); + } + + public QueryDefinition select(SelectItem... selectItems) { + return _owner.select(selectItems); + } + + public QueryDefinition select(List selectItemList) { + return _owner.select(selectItemList); + } + + public QueryDefinition selectDistinct(SelectItem... selectItems) { + return _owner.selectDistinct(selectItems); + } + + public QueryDefinition selectDistinct(List selectItemList) { + return _owner.selectDistinct(selectItemList); + } + + public CaseExpression simpleCase(Expression caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(Number caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(String caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(Date caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(Calendar caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(Class caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public CaseExpression simpleCase(Enum caseOperand) { + return _owner.simpleCase(caseOperand); + } + + public QueryDefinition where(Predicate predicate) { + return _owner.where(predicate); + } + + // ----------------------------------------------------------------------- + // contract for conversion to JPQL. + // ----------------------------------------------------------------------- + /** + * Sets alias for this domain and all its joins. + */ + public void setAlias(AliasContext ctx) { + ctx.getAlias(this); + if (_joins != null) + for (JoinPath join : _joins) + join.setAlias(ctx); + } + + abstract public String asJoinable(AliasContext ctx); + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java new file mode 100644 index 000000000..9c89573b9 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AbstractPath.java @@ -0,0 +1,124 @@ +/* + * 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.query; + +import javax.persistence.Aggregate; +import javax.persistence.Expression; +import javax.persistence.OrderByItem; +import javax.persistence.PathExpression; +import javax.persistence.Predicate; + +/** + * An abstract path is formed by two parts : the first part is a parent path. + * The second part can be an attribute or an operation (e.g. KEY() or VALUE()) + * or a join type operation. Based on the exact nature of the second part, + * concrete derivation of this class combines the two constituent parts to + * arrive at complete path name. + * For example, a navigation path adds the two part with a navigation '.' + * operator, while a OperatorPath will combine the parts as KEY(parent). + * + * The constituent parts are immutable and supplied at construction. Hence + * concrete implementations know what exact type they are dealing with, but + * this receiver maintains it state as more generic type to accommodate + * concrete types to cast/interpret these state variables. + * + * @author Pinaki Poddar + * + */ +abstract class AbstractPath extends ExpressionImpl implements + PathExpression { + protected final AbstractPath _parent; + protected final Object _part2; + protected final PathOperator _operator; + + protected AbstractPath(AbstractPath parent, PathOperator op, Object part2) { + _parent = parent; + _part2 = part2; + _operator = op; + } + + // ------------------------------------------------------------------------ + // Path related functions. + // ------------------------------------------------------------------------ + /** + * Gets the parent from which this receiver has been derived. Can be null + * for a root path. + */ + public AbstractPath getParent() { + return _parent; + } + + /** + * Gets operator that derived this receiver from its parent. + */ + public PathOperator getOperator() { + return _operator; + } + + /** + * Gets the last segment of this path. + * Concrete implementation should return a covariant type. + */ + public Object getLastSegment() { + return _part2; + } + + // ----------------------------------------------------------------------- + // Implementation of PathExpression + // ----------------------------------------------------------------------- + public Aggregate avg() { + return new AverageExpression(this); + } + + public Aggregate count() { + return new CountExpression(this); + } + + public Predicate isEmpty() { + return new IsEmptyExpression(this); + } + + public Aggregate max() { + return new MaxExpression(this); + } + + public Aggregate min() { + return new MinExpression(this); + } + + public Expression size() { + return new SizeExpression(this); + } + + public Aggregate sum() { + return new SumExpression(this); + } + + public Expression type() { + return new TypeExpression(this); + } + + public OrderByItem asc() { + return new OrderableItem(this, Boolean.TRUE); + } + + public OrderByItem desc() { + return new OrderableItem(this, Boolean.FALSE); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java new file mode 100644 index 000000000..919f3abca --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AliasContext.java @@ -0,0 +1,60 @@ +/* + * 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.query; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.Expression; + +class AliasContext { + private Map _aliases = + new HashMap(); + + /** + * Sets alias for the given Expression or gets the alias if the given + * path has already been assigned an alias. + * The given expression must provide a hint on what should be the + * alias name. If the alias name is assigned by this context, then a + * different alias is generated. + * @param path + * @return the alias name + */ + public String getAlias(ExpressionImpl path) { + String alias = _aliases.get(path); + if (alias != null) + return alias; + alias = path.getAliasHint().substring(0,1).toLowerCase(); + int i = 2; + while (_aliases.containsValue(alias)) { + alias = alias + i; + i++; + } + _aliases.put(path, alias); + return alias; + } + + /** + * Affirms if the given Expression has been assigned an alias by this + * context. + */ + public boolean hasAlias(Expression path) { + return _aliases.containsKey(path); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AllExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AllExpression.java new file mode 100644 index 000000000..2bf922b94 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AllExpression.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.DomainObject; +import javax.persistence.QueryDefinition; +import javax.persistence.Subquery; + +/** + * Denotes All(SubQuery) Expression. + * + * @author Pinaki Poddar + * + */ +class AllExpression extends QueryExpression implements Subquery { + public AllExpression(QueryDefinitionImpl sub) { + super(sub, UnaryFunctionalOperator.ALL); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AndPredicate.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AndPredicate.java new file mode 100644 index 000000000..05d0dab51 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AndPredicate.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Predicate; +import static org.apache.openjpa.persistence.query.ConditionalOperator.*; + +/** + * Denotes (e1 AND e2) predicate. + * + * @author Pinaki Poddar + * + */ +public class AndPredicate extends LogicalPredicate { + public AndPredicate(Predicate p1, Predicate p2) { + super(p1, AND, OR, p2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AnyExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AnyExpression.java new file mode 100644 index 000000000..16dbb04ce --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AnyExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.QueryDefinition; +import javax.persistence.Subquery; + +/** + * Denotes ANY(SUbquery) Expression. + * + * @author Pinaki Poddar + * + */ +class AnyExpression extends UnaryOperatorExpression implements Subquery { + public AnyExpression(QueryDefinitionImpl sub) { + super(sub, UnaryFunctionalOperator.ANY); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AverageExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AverageExpression.java new file mode 100644 index 000000000..22e90f12e --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/AverageExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes AVG() on a given Expression. + * + * @author Pinaki Poddar + * + */ +public class AverageExpression extends UnaryOperatorExpression { + public AverageExpression(ExpressionImpl op) { + super(op, UnaryFunctionalOperator.AVG); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BetweenExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BetweenExpression.java new file mode 100644 index 000000000..d464ec5c0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BetweenExpression.java @@ -0,0 +1,39 @@ +/* + * 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.query; + +import javax.persistence.Expression; + + +/** + * Denotes e1 BETWEEN(e2 AND e3) Expression. + * + * @author Pinaki Poddar + * + */ +public class BetweenExpression extends BinaryExpressionPredicate { + public BetweenExpression(Expression arg1, RangeExpression arg2) { + super(arg1, BinaryConditionalOperator.BETWEEN, + BinaryConditionalOperator.BETWEEN_NOT, arg2); + } + +// public String toJPQL(AliasContext ctx) { +// return super.toJPQL(ctx) + " AND " + ((ExpressionImpl)arg3).toJPQL(ctx); +// } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryConditionalOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryConditionalOperator.java new file mode 100644 index 000000000..5a689d484 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryConditionalOperator.java @@ -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.query; + +/** + * Enumeration of conditional operator that operates on ordered pair of + * expression to generate a predicate. + * + * @see BinaryExpressionPredicate + * + * @author Pinaki Poddar + * + */ +public enum BinaryConditionalOperator { + BETWEEN("BETWEEN"), + BETWEEN_NOT("NOT BETWEEN"), + EQUAL("="), + EQUAL_NOT("<>"), + GREATER(">"), + GREATEREQUAL(">="), + IN("IN"), + IN_NOT("NOT IN"), + LESS("<"), + LESSEQUAL("<="), + LIKE("LIKE"), + LIKE_NOT("NOT LIKE"), + MEMBER("MEMBER OF"), + MEMBER_NOT("NOT MEMBER OF"); + + private final String _symbol; + + BinaryConditionalOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryExpressionPredicate.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryExpressionPredicate.java new file mode 100644 index 000000000..b50529b97 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryExpressionPredicate.java @@ -0,0 +1,75 @@ +/* + * 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.query; + +import javax.persistence.Expression; +import javax.persistence.Predicate; + +/** + * Binary predicate combines two expressions with an operator. + * + * @author Pinaki Poddar + * + */ +class BinaryExpressionPredicate implements Predicate, Visitable { + protected final Expression _e1; + protected final Expression _e2; + protected final BinaryConditionalOperator _op; + private final BinaryConditionalOperator _nop; + + BinaryExpressionPredicate(Expression e1, BinaryConditionalOperator op, + BinaryConditionalOperator nop, Expression e2) { + _e1 = e1; + _e2 = e2; + _op = op; + _nop = nop; + } + + public final Expression getOperand() { + return _e1; + } + + public final Expression getOperand2() { + return _e2; + } + + public final BinaryConditionalOperator getOperator() { + return _op; + } + + public Predicate and(Predicate predicate) { + return new AndPredicate(this, predicate); + } + + public Predicate or(Predicate predicate) { + return new OrPredicate(this, predicate); + } + + public Predicate not() { + if ( _nop == null) + throw new UnsupportedOperationException(this.toString()); + return new BinaryExpressionPredicate(_e1, _nop, _op, _e2); + } + + public String asExpression(AliasContext ctx) { + return ((Visitable)_e1).asExpression(ctx) + + " " + _op + " " + + ((Visitable)_e2).asExpression(ctx); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryFunctionalOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryFunctionalOperator.java new file mode 100644 index 000000000..ff82cadf7 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryFunctionalOperator.java @@ -0,0 +1,50 @@ +/* + * 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.query; + +/** + * Enumeration of functional operator that operates on ordered pair of + * expression to generate another expression. + * + * @see BinaryOperatorExpression + * + * @author Pinaki Poddar + * + */ +public enum BinaryFunctionalOperator { + DIVIDE("/"), + LOCATE("LOCATE"), + MINUS("-"), + MOD("MOD"), + PLUS("+"), + RANGE(","), + SUBSTR("SUBSTR"), + TIMES("*"), + TRIM("TRIM"); + + private final String _symbol; + + BinaryFunctionalOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryOperatorExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryOperatorExpression.java new file mode 100644 index 000000000..9d7afa690 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/BinaryOperatorExpression.java @@ -0,0 +1,62 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * An expression resulting from a binary operation on two expressions. + * + * @author Pinaki Poddar + * + */ +public class BinaryOperatorExpression extends ExpressionImpl { + protected final Expression _e1; + protected final Expression _e2; + protected final BinaryFunctionalOperator _op; + + public BinaryOperatorExpression(Expression e1, BinaryFunctionalOperator op, + Expression e2) { + _e1 = e1; + _e2 = e2; + _op = op; + } + + public Expression getOperand1() { + return _e1; + } + + public Expression getOperand2() { + return _e2; + } + + public BinaryFunctionalOperator getOperator() { + return _op; + } + + public String asExpression(AliasContext ctx) { + return ((Visitable)_e1).asExpression(ctx) + _op + + ((Visitable)_e2).asExpression(ctx); + } + + public String asProjection(AliasContext ctx) { + return ((Selectable)_e1).asProjection(ctx) + _op + + ((Selectable)_e2).asProjection(ctx); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CaseExpressionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CaseExpressionImpl.java new file mode 100644 index 000000000..9d04a4618 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CaseExpressionImpl.java @@ -0,0 +1,197 @@ +/* + * 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.query; + +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedList; + +import javax.persistence.CaseExpression; +import javax.persistence.Expression; +import javax.persistence.Predicate; + +public class CaseExpressionImpl implements CaseExpression { + private LinkedList _whens = new LinkedList(); + private final Object _caseOperand; + + public CaseExpressionImpl() { + this(null); + } + + public CaseExpressionImpl(Object caseOperand) { + _caseOperand = caseOperand; + } + + public Expression elseCase(Expression arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(String arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(Number arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(Date arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(Calendar arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(Class arg) { + return new ElseExpression(this, arg); + } + + public Expression elseCase(Enum arg) { + return new ElseExpression(this, arg); + } + + public CaseExpression then(Expression then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(Number then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(String then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(Date then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(Calendar then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(Class then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression then(Enum then) { + assertThenState(); + _whens.getLast().setThen(then); + return this; + } + + public CaseExpression when(Predicate when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Expression when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Number when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(String when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Date when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Calendar when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Class when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + public CaseExpression when(Enum when) { + assertWhenState(); + WhenClause clause = new WhenClause(when); + _whens.add(clause); + return this; + } + + void assertWhenState() { + boolean ok = _whens.isEmpty() || _whens.getLast().hasThen(); + if (!ok) + throw new IllegalStateException("when() can not be called now"); + } + + void assertThenState() { + boolean ok = !_whens.isEmpty() && !_whens.getLast().hasThen(); + if (!ok) + throw new IllegalStateException("then() can not be called now"); + } + + public String toJPQL(AliasContext ctx) { + StringBuffer tmp = new StringBuffer("CASE "); + if (_caseOperand != null) { + tmp.append(toJPQL(ctx, _caseOperand)); + } + for (WhenClause when : _whens) { + tmp.append(when.toJPQL(ctx)); + } + return tmp.toString(); + } + + + String toJPQL(AliasContext ctx, Object o) { + if (o instanceof Visitable) { + return ((Visitable)o).asExpression(ctx); + } + return o.toString(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConditionalOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConditionalOperator.java new file mode 100644 index 000000000..6f0acf587 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConditionalOperator.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Enumerates conditional operator that operates on two predicates to generate + * another predicate. + * + * @author Pinaki Poddar + * + */ +public enum ConditionalOperator { + AND, + OR; +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConstantExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConstantExpression.java new file mode 100644 index 000000000..d7405f754 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ConstantExpression.java @@ -0,0 +1,60 @@ +/* + * 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.query; + +import java.util.Arrays; + +/** + * Denotes a Value based expression such as Number, String or Date. + * + * @author Pinaki Poddar + * + */ +class ConstantExpression extends ExpressionImpl { + private final Object _value; + + public ConstantExpression(Object value) { + _value = value; + } + + public Object getValue() { + return _value; + } + + @Override + public String asExpression(AliasContext ctx) { + if (_value.getClass().isArray()) { + return Arrays.asList((Object[])_value).toString(); + } + return quoted(_value); + } + + @Override + public String asProjection(AliasContext ctx) { + return asExpression(ctx); + } + + String quoted(Object o) { + if (o instanceof String) + return "'" + o + "'"; + if (o instanceof Class) + return ((Class)o).getSimpleName(); + return o.toString(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CountExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CountExpression.java new file mode 100644 index 000000000..d5dd6f3e4 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CountExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes COUNT(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class CountExpression extends UnaryOperatorExpression { + public CountExpression(Expression op) { + super(op, UnaryFunctionalOperator.COUNT); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CurrentTimeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CurrentTimeExpression.java new file mode 100644 index 000000000..2f870bb59 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/CurrentTimeExpression.java @@ -0,0 +1,56 @@ +/* + * 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.query; + +import java.sql.Time; +import java.util.Date; + +/** + * Denotes CURRENT_TIME(), CURRENT_DATE() and CURRENT_TIMESTAMP() expressions. + * + * @author Pinaki Poddar + * + */ +public class CurrentTimeExpression extends ExpressionImpl { + private static enum Now { + CURRENT_DATE, + CURRENT_TIME, + CURRENT_TIMESTAMP + } + + private final Class _type; + + public CurrentTimeExpression(Class operand) { + _type = operand; + } + + @Override + public String asExpression(AliasContext ctx) { + Now now = (_type == Date.class + ? Now.CURRENT_DATE + : (_type == Time.class + ? Now.CURRENT_TIME : Now.CURRENT_TIMESTAMP)); + return now.toString(); + } + + @Override + public String asProjection(AliasContext ctx) { + throw new UnsupportedOperationException(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DistinctExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DistinctExpression.java new file mode 100644 index 000000000..870dd8de0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DistinctExpression.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes DISTINCT(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class DistinctExpression extends UnaryOperatorExpression { + + public DistinctExpression(Expression expr) { + super(expr, UnaryFunctionalOperator.DISTINCT); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DividedByExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DividedByExpression.java new file mode 100644 index 000000000..fdb14c885 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/DividedByExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1/e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class DividedByExpression extends BinaryOperatorExpression { + public DividedByExpression(Expression op1, Expression op2) { + super(op1, BinaryFunctionalOperator.DIVIDE, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ElseExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ElseExpression.java new file mode 100644 index 000000000..2ca469dea --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ElseExpression.java @@ -0,0 +1,63 @@ +/* + * 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.query; + +/** + * Else clause in a Case Statement. + * + * @author Pinaki Poddar + * + */ +public class ElseExpression extends ExpressionImpl { + private final CaseExpressionImpl _caseClause; + private final Object _elseClause; + + public ElseExpression(CaseExpressionImpl owner, Object op) { + _caseClause = owner; + _elseClause = op; + } + + @Override + public String asExpression(AliasContext ctx) { + return _caseClause.toJPQL(ctx) + + " ELSE " + toJPQL(ctx, _elseClause) + + " END "; + } + + @Override + public String asProjection(AliasContext ctx) { + return _caseClause.toJPQL(ctx) + + " ELSE " + toJPQL(ctx, _elseClause) + + " END "; + } + + String toJPQL(AliasContext ctx, Object o) { + if (o instanceof Visitable) { + return ((Visitable)o).asExpression(ctx); + } + return o.toString(); + } + + String asProjection(AliasContext ctx, Object o) { + if (o instanceof Selectable) { + return ((Selectable)o).asProjection(ctx); + } + return o.toString(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EntryExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EntryExpression.java new file mode 100644 index 000000000..e2d8a9460 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EntryExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes ENTRY(e) on a path. + * + * @author Pinaki Poddar + * + */ +public class EntryExpression extends OperatorPath { + public EntryExpression(AbstractDomainObject expr) { + super(expr, PathOperator.ENTRY); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EqualExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EqualExpression.java new file mode 100644 index 000000000..9d80c4b1f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/EqualExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 = e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class EqualExpression extends BinaryExpressionPredicate { + public EqualExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.EQUAL, BinaryConditionalOperator.EQUAL_NOT, op2); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExistsExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExistsExpression.java new file mode 100644 index 000000000..5b4c74b92 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExistsExpression.java @@ -0,0 +1,32 @@ +/* + * 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.query; + +/** + * Denotes EXISTS(SubQuery) Expression. + * + * @author Pinaki Poddar + * + */ +public class ExistsExpression extends UnaryExpressionPredicate { + public ExistsExpression(QueryDefinitionImpl op) { + super(op, UnaryConditionalOperator.EXISTS, UnaryConditionalOperator.EXISTS_NOT); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java new file mode 100644 index 000000000..d2288fbf4 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ExpressionImpl.java @@ -0,0 +1,477 @@ +/* + * 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.query; + +import java.util.Calendar; +import java.util.Date; + +import javax.persistence.Expression; +import javax.persistence.OrderByItem; +import javax.persistence.PathExpression; +import javax.persistence.Predicate; +import javax.persistence.PredicateOperand; +import javax.persistence.Subquery; +import javax.persistence.TrimSpec; + +/** + * An abstract expression acts as a factory for concrete unary or binary + * expressions such as ABS() or PLUS(). + * + * @author Pinaki Poddar + * + */ +abstract class ExpressionImpl implements Expression, Selectable, Visitable { + + public Expression abs() { + return new AbsExpression(this); + } + + public Expression concat(String... str) { + throw new UnsupportedOperationException(); + } + + public Expression concat(Expression... str) { + throw new UnsupportedOperationException(); + } + + public Expression dividedBy(Number num) { + return new DividedByExpression(this, new ConstantExpression(num)); + } + + public Expression dividedBy(Expression expr) { + return new DividedByExpression(this, expr); + } + + public Predicate in(String... strings) { + return new InExpression(this, new ConstantExpression(strings)); + } + + public Predicate in(Number... nums) { + return new InExpression(this, + new ConstantExpression(nums)); + } + + public Predicate in(Enum... enums) { + return new InExpression(this, + new ConstantExpression(enums)); + } + + public Predicate in(Class... classes) { + return new InExpression(this, + new ConstantExpression(classes)); + } + + public Predicate in(Expression... params) { + return new InExpression(this, + new ConstantExpression(params)); + } + + public Predicate in(Subquery subquery) { + return new InExpression(this, (Expression)subquery); + } + + public Predicate isNull() { + return new IsNullExpression(this); + } + + public Expression length() { + return new LengthExpression(this); + } + + public Expression locate(String str) { + return locate(str, 0); + } + + public Expression locate(Expression expr) { + return new LocateExpression(this, expr, 1); + } + + public Expression locate(String str, int position) { + return new LocateExpression(this, new ConstantExpression(str), position); + } + + public Expression locate(String str, Expression position) { + return new LocateExpression(this, new ConstantExpression(str), position); + } + + public Expression locate(Expression str, int position) { + return new LocateExpression(this, str, position); + } + + public Expression locate(Expression str, Expression position) { + return new LocateExpression(this, str, position); + } + + public Expression lower() { + return new LowerExpression(this); + } + + public Predicate member(PathExpression arg) { + return new MemberOfExpression(this, arg); + } + + public Expression minus() { + return new UnaryMinusExpression(this); + } + + public Expression minus(Number num) { + return new MinusExpression(this, new ConstantExpression(num)); + } + + public Expression minus(Expression expr) { + return new MinusExpression(this, expr); + } + + public Expression mod(int num) { + return new ModExpression(this, new ConstantExpression(num)); + } + + public Expression mod(Expression expr) { + return new MinusExpression(this, expr); + } + + public Expression plus(Number num) { + return new PlusExpression(this, new ConstantExpression(num)); + } + + public Expression plus(Expression expr) { + return new PlusExpression(this, expr); + } + + public Expression sqrt() { + return new SquareRootExpression(this); + } + + public Expression substring(int start) { + return new SubStringExpression(this, start); + } + + public Expression substring(Expression start) { + return new SubStringExpression(this, start); + } + + public Expression substring(int start, int len) { + return new SubStringExpression(this, start, len); + } + + public Expression substring(int start, Expression len) { + return new SubStringExpression(this, new ConstantExpression(start), len); + } + + public Expression substring(Expression start, int len) { + return new SubStringExpression(this, start, new ConstantExpression(len)); + } + + public Expression substring(Expression start, Expression len) { + return new SubStringExpression(this, start, len); + } + + public Expression times(Number num) { + return new TimesExpression(this, new ConstantExpression(num)); + } + + public Expression times(Expression expr) { + return new TimesExpression(this, expr); + } + + public Expression trim() { + return new TrimExpression(this, null, null); + } + + public Expression trim(TrimSpec spec) { + return new TrimExpression(this, null, spec); + } + + public Expression trim(char c) { + return new TrimExpression(this, c, null); + } + + public Expression trim(char c, TrimSpec spec) { + return new TrimExpression(this, c, spec); + } + + public Expression trim(Expression expr) { + return new TrimExpression(this, expr, null); + } + + public Expression trim(Expression expr, TrimSpec spec) { + return new TrimExpression(this, expr, spec); + } + + public Expression upper() { + return new ToUpperExpression(this); + } + + public OrderByItem asc() { + throw new UnsupportedOperationException(this.toString()); + } + + public OrderByItem desc() { + throw new UnsupportedOperationException(this.toString()); + } + + public Predicate between(PredicateOperand arg1, PredicateOperand arg2) { + return new BetweenExpression(this, new RangeExpression( + (Expression)arg1, (Expression)arg2)); + } + + public Predicate between(PredicateOperand arg1, Number arg2) { + return new BetweenExpression(this, new RangeExpression( + (Expression)arg1, new ConstantExpression(arg2))); + } + + public Predicate between(Number arg1, PredicateOperand arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), (Expression)arg2)); + } + + public Predicate between(Number arg1, Number arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), new ConstantExpression(arg2))); + } + + public Predicate between(PredicateOperand arg1, String arg2) { + return new BetweenExpression(this, new RangeExpression((Expression)arg1, + new ConstantExpression(arg2))); + } + + public Predicate between(String arg1, PredicateOperand arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), (Expression)arg2)); + } + + public Predicate between(String arg1, String arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), new ConstantExpression(arg2))); + } + + public Predicate between(PredicateOperand arg1, Date arg2) { + return new BetweenExpression(this, new RangeExpression( + (Expression)arg1, new ConstantExpression(arg2))); + } + + public Predicate between(Date arg1, PredicateOperand arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), (Expression)arg2)); + } + + public Predicate between(Date arg1, Date arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), new ConstantExpression(arg2))); + } + + public Predicate between(PredicateOperand arg1, Calendar arg2) { + return new BetweenExpression(this, new RangeExpression( + (Expression)arg1, new ConstantExpression(arg2))); + } + + public Predicate between(Calendar arg1, PredicateOperand arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), (Expression)arg2)); + } + + public Predicate between(Calendar arg1, Calendar arg2) { + return new BetweenExpression(this, new RangeExpression( + new ConstantExpression(arg1), new ConstantExpression(arg2))); + } + + public Predicate equal(PredicateOperand arg) { + return new EqualExpression(this, (Expression)arg); + } + + public Predicate equal(Class cls) { + return new EqualExpression(this, new ConstantExpression(cls)); + } + + public Predicate equal(Number arg) { + return new EqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate equal(String arg) { + return new EqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate equal(boolean arg) { + return new EqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate equal(Date arg) { + return new EqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate equal(Calendar arg) { + return new EqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate equal(Enum e) { + return new EqualExpression(this, new ConstantExpression(e)); + } + + public Predicate greaterEqual(PredicateOperand arg) { + return new GreaterEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterEqual(Number arg) { + return new GreaterEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterEqual(String arg) { + return new GreaterEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterEqual(Date arg) { + return new GreaterEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterEqual(Calendar arg) { + return new GreaterEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterThan(PredicateOperand arg) { + return new GreaterThanExpression(this, (Expression)arg); + } + + public Predicate greaterThan(Number arg) { + return new GreaterThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterThan(String arg) { + return new GreaterThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterThan(Date arg) { + return new GreaterThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate greaterThan(Calendar arg) { + return new GreaterThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessEqual(PredicateOperand arg) { + return new LessEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessEqual(Number arg) { + return new LessEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessEqual(String arg) { + return new LessEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessEqual(Date arg) { + return new LessEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessEqual(Calendar arg) { + return new LessEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessThan(PredicateOperand arg) { + return new LessThanExpression(this, (Expression)arg); + } + + public Predicate lessThan(Number arg) { + return new LessThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessThan(String arg) { + return new LessThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessThan(Date arg) { + return new LessThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate lessThan(Calendar arg) { + return new LessThanExpression(this, new ConstantExpression(arg)); + } + + public Predicate like(PredicateOperand pattern) { + return new LikeExpression(this, (Expression)pattern, null); + } + + public Predicate like(PredicateOperand pattern, PredicateOperand escChar) { + return new LikeExpression(this, (Expression)pattern, escChar); + } + + public Predicate like(PredicateOperand pattern, char escapeChar) { + return new LikeExpression(this, (Expression)pattern, escapeChar); + } + + public Predicate like(String pattern) { + return new LikeExpression(this, new ConstantExpression(pattern), null); + } + + public Predicate like(String pattern, PredicateOperand escapeChar) { + return new LikeExpression(this, new ConstantExpression(pattern), + escapeChar); + } + + public Predicate like(String pattern, char escChar) { + return new LikeExpression(this, new ConstantExpression(pattern), + escChar); + } + + public Predicate notEqual(PredicateOperand arg) { + return new NotEqualExpression(this, (Expression)arg); + } + + public Predicate notEqual(Class cls) { + return new NotEqualExpression(this, new ConstantExpression(cls)); + } + + public Predicate notEqual(Number arg) { + return new NotEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate notEqual(String arg) { + return new NotEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate notEqual(boolean arg) { + return new NotEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate notEqual(Date arg) { + return new NotEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate notEqual(Calendar arg) { + return new NotEqualExpression(this, new ConstantExpression(arg)); + } + + public Predicate notEqual(Enum e) { + return new NotEqualExpression(this, new ConstantExpression(e)); + } + + // + // Visitable/Selectable implementation + // + public void setAlias(AliasContext ctx) { + ctx.getAlias(this); + } + + public String getAliasHint() { + return "o"; + } + + public abstract String asExpression(AliasContext ctx); + public abstract String asProjection(AliasContext ctx); +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java new file mode 100644 index 000000000..ccf8fddf0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/FetchPath.java @@ -0,0 +1,42 @@ +/* + * 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.query; + +import javax.persistence.FetchJoinObject; + +/** + * Denotes a path used in fetch join. Simply wraps a Navigation Path. + * + * @author Pinaki Poddar + * + */ +public class FetchPath implements FetchJoinObject, Visitable { + private NavigationPath _path; + private PathOperator _joinType; + + + FetchPath(NavigationPath path, PathOperator joinType) { + _path = path; + _joinType = joinType; + } + + public String asExpression(AliasContext ctx) { + return _joinType + " " + _path.asExpression(ctx); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterEqualExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterEqualExpression.java new file mode 100644 index 000000000..f7c483ab0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterEqualExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 >= e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class GreaterEqualExpression extends BinaryExpressionPredicate { + public GreaterEqualExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.GREATEREQUAL, BinaryConditionalOperator.LESS, op2); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterThanExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterThanExpression.java new file mode 100644 index 000000000..67b9feb2e --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/GreaterThanExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 > e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class GreaterThanExpression extends BinaryExpressionPredicate { + public GreaterThanExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.GREATER, BinaryConditionalOperator.LESSEQUAL, op2); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/InExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/InExpression.java new file mode 100644 index 000000000..f0c4189f5 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/InExpression.java @@ -0,0 +1,15 @@ +package org.apache.openjpa.persistence.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 IN (e2) Expression. + * + * @author Pinaki Poddar + * + */ +public class InExpression extends BinaryExpressionPredicate { + public InExpression(Expression op, Expression op2) { + super(op, BinaryConditionalOperator.IN, BinaryConditionalOperator.IN_NOT, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IndexExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IndexExpression.java new file mode 100644 index 000000000..6865d9bc9 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IndexExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes INDEX(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class IndexExpression extends UnaryOperatorExpression { + public IndexExpression(Expression op) { + super(op, UnaryFunctionalOperator.INDEX); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsEmptyExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsEmptyExpression.java new file mode 100644 index 000000000..bdc2ae2be --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsEmptyExpression.java @@ -0,0 +1,16 @@ +package org.apache.openjpa.persistence.query; + +import javax.persistence.Expression; + + +public class IsEmptyExpression extends UnaryExpressionPredicate { + public IsEmptyExpression(Expression op) { + super(op, UnaryConditionalOperator.ISEMPTY, + UnaryConditionalOperator.ISEMPTY_NOT); + } + + @Override + public String asExpression(AliasContext ctx) { + return ((Visitable)_e).asExpression(ctx) + " " + _op; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsNullExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsNullExpression.java new file mode 100644 index 000000000..f87420019 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/IsNullExpression.java @@ -0,0 +1,39 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e IS NULL Expression. + * + * @author Pinaki Poddar + * + */ +public class IsNullExpression extends UnaryExpressionPredicate { + public IsNullExpression(Expression op) { + super(op, UnaryConditionalOperator.ISNULL, + UnaryConditionalOperator.ISNULL_NOT); + } + + @Override + public String asExpression(AliasContext ctx) { + return ((Visitable)_e).asExpression(ctx) + " " + _op; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JPQLHelper.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JPQLHelper.java new file mode 100644 index 000000000..028a69ac7 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JPQLHelper.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +/** + * Utility for converting elements to JPQL string fragments. + * + * @author Pinaki Poddar + * + */ +public class JPQLHelper { + static String toJPQL(AliasContext ctx, Object o) { + if (o instanceof Visitable) + return ((Visitable)o).asExpression(ctx); + return o.toString(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java new file mode 100644 index 000000000..a1445ff25 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/JoinPath.java @@ -0,0 +1,78 @@ +/* + * 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.query; + +import javax.persistence.DomainObject; +import static org.apache.openjpa.persistence.query.PathOperator.NAVIGATION; + +/** + * Path resulting by joining from a parent path via an attribute. + * + * @author Pinaki Poddar + * + */ +public class JoinPath extends AbstractDomainObject implements DomainObject { + public JoinPath(AbstractDomainObject parent, PathOperator join, String attr) { + super(parent.getOwner(), parent, join, attr); + } + + @Override + public String getAliasHint() { + return getLastSegment(); + } + + @Override + public String getLastSegment() { + return super.getLastSegment().toString(); + } + + @Override + public AbstractDomainObject getParent() { + return (AbstractDomainObject)super.getParent(); + } + +// @Override + public String asJoinable(AliasContext ctx) { + StringBuffer tmp = new StringBuffer(getOperator().toString()); + tmp.append(getParent().asProjection(ctx)) + .append(NAVIGATION) + .append(getLastSegment()) + .append(" ") + .append(ctx.getAlias(this)); + + if (getJoins() != null) + for (JoinPath join : getJoins()) + tmp.append(join.asJoinable(ctx)); + return tmp.toString(); + } + + @Override + public String asExpression(AliasContext ctx) { + if (ctx.hasAlias(this)) + return ctx.getAlias(this); + return getParent().asExpression(ctx) + NAVIGATION + getLastSegment(); + } + + @Override + public String asProjection(AliasContext ctx) { + if (ctx.hasAlias(this)) + return ctx.getAlias(this); + return getParent().asProjection(ctx) + NAVIGATION + getLastSegment(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/KeyExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/KeyExpression.java new file mode 100644 index 000000000..ad1f9a3dd --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/KeyExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes KEY(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class KeyExpression extends OperatorPath { + public KeyExpression(AbstractDomainObject expr) { + super(expr, PathOperator.KEY); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LengthExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LengthExpression.java new file mode 100644 index 000000000..c1d973f7e --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LengthExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes LENGTH(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class LengthExpression extends UnaryOperatorExpression { + public LengthExpression(Expression op) { + super(op, UnaryFunctionalOperator.LENGTH); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessEqualExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessEqualExpression.java new file mode 100644 index 000000000..d42aa5fc3 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessEqualExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 <= e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class LessEqualExpression extends BinaryExpressionPredicate { + public LessEqualExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.LESSEQUAL, + BinaryConditionalOperator.GREATER, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessThanExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessThanExpression.java new file mode 100644 index 000000000..25c570791 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LessThanExpression.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 < e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class LessThanExpression extends BinaryExpressionPredicate { + public LessThanExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.LESS, + BinaryConditionalOperator.GREATEREQUAL, op2); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LikeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LikeExpression.java new file mode 100644 index 000000000..2b32b5883 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LikeExpression.java @@ -0,0 +1,44 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 LIKE e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class LikeExpression extends BinaryExpressionPredicate { + public LikeExpression(Expression op1, Expression op2, Object echar) { + super(escape(op1, echar), BinaryConditionalOperator.LIKE, + BinaryConditionalOperator.LIKE_NOT, escape(op2, echar)); + } + + static Expression escape(Expression o, Object echar) { + if (echar != null && o instanceof ConstantExpression + && ((ConstantExpression)o).getValue() instanceof String) { + String escapeChar = echar.toString(); + return new ConstantExpression(escapeChar + o.toString() + escapeChar); + } + return o; + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LiteralExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LiteralExpression.java new file mode 100644 index 000000000..53fee80cd --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LiteralExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes a Literal Expression. + * + * @author Pinaki Poddar + * + */ +public class LiteralExpression extends ConstantExpression { + public LiteralExpression(Object literal) { + super(literal); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LocateExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LocateExpression.java new file mode 100644 index 000000000..5905a9b21 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LocateExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes LOCATE(e) + * + * @author Pinaki Poddar + * + */ +public class LocateExpression extends BinaryOperatorExpression { + public LocateExpression(Expression op, Expression op2, Object pos) { + super(op, BinaryFunctionalOperator.LOCATE, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LogicalPredicate.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LogicalPredicate.java new file mode 100644 index 000000000..4c676a185 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LogicalPredicate.java @@ -0,0 +1,59 @@ +/* + * 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.query; + +import javax.persistence.Predicate; + +/** + * Logical Predicate combines two predicates with a logical operator. + * + * @author Pinaki Poddar + * + */ +public class LogicalPredicate implements Predicate, Visitable { + private final Predicate _p1; + private final Predicate _p2; + private final ConditionalOperator _op; + private final ConditionalOperator _nop; + + public LogicalPredicate(Predicate p1, ConditionalOperator op, + ConditionalOperator nop, Predicate p2) { + _p1 = p1; + _p2 = p2; + _op = op; + _nop = nop; + } + + public Predicate and(Predicate predicate) { + return new AndPredicate(this, predicate); + } + + public Predicate or(Predicate predicate) { + return new OrPredicate(this, predicate); + } + + public Predicate not() { + return new LogicalPredicate(_p1.not(), _nop, _op, _p2.not()); + } + + public String asExpression(AliasContext ctx) { + return ((Visitable)_p1).asExpression(ctx) + " " + _op + " " + + ((Visitable)_p2).asExpression(ctx); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LowerExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LowerExpression.java new file mode 100644 index 000000000..790059aae --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/LowerExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes LOWER(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class LowerExpression extends UnaryOperatorExpression { + public LowerExpression(Expression op) { + super(op, UnaryFunctionalOperator.LOWER); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MaxExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MaxExpression.java new file mode 100644 index 000000000..883c00704 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MaxExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes MAX(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class MaxExpression extends UnaryOperatorExpression { + public MaxExpression(Expression op) { + super(op, UnaryFunctionalOperator.MAX); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MemberOfExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MemberOfExpression.java new file mode 100644 index 000000000..6a2e75645 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MemberOfExpression.java @@ -0,0 +1,34 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes e1 MEMBER OF e2 Expression. + * + * @author Pinaki Poddar + * + */ +public class MemberOfExpression extends BinaryExpressionPredicate { + public MemberOfExpression(Expression op, Expression op2) { + super(op, BinaryConditionalOperator.MEMBER, + BinaryConditionalOperator.MEMBER_NOT, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinExpression.java new file mode 100644 index 000000000..f34b6f473 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes MIN(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class MinExpression extends UnaryOperatorExpression { + public MinExpression(Expression op) { + super(op, UnaryFunctionalOperator.MIN); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinusExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinusExpression.java new file mode 100644 index 000000000..def1e822f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/MinusExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes (e1 - e2) Expression. + * + * @author Pinaki Poddar + * + */ +public class MinusExpression extends BinaryOperatorExpression { + public MinusExpression(Expression op, Expression op2) { + super(op, BinaryFunctionalOperator.MINUS, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ModExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ModExpression.java new file mode 100644 index 000000000..0f3003315 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ModExpression.java @@ -0,0 +1,37 @@ +/* + * 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.query; + +/** + * Denotes MOD(e1, e2) Expression. + * + * @author Pinaki Poddar + * + */ +class ModExpression extends BinaryOperatorExpression { + public ModExpression(ExpressionImpl op, ExpressionImpl op2) { + super(op, BinaryFunctionalOperator.MOD, op2); + } + + @Override + public String asExpression(AliasContext ctx) { + return _op + "(" + ((Visitable)_e1).asExpression(ctx) + + "," + ((Visitable)_e2).asExpression(ctx); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java new file mode 100644 index 000000000..9c5cfdc0e --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NavigationPath.java @@ -0,0 +1,62 @@ +/* + * 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.query; + +import javax.persistence.PathExpression; +import static org.apache.openjpa.persistence.query.PathOperator.NAVIGATION; +/** + * Represents a path resulted by navigation. + * + * @author Pinaki Poddar + * + */ +class NavigationPath extends AbstractDomainObject implements PathExpression { + protected NavigationPath(QueryDefinitionImpl owner, AbstractPath parent, + String attr) { + super(owner, parent, NAVIGATION, attr); + } + + @Override + public String getLastSegment() { + return (String)super.getLastSegment(); + } + + @Override + public String asProjection(AliasContext ctx) { + AbstractPath parent = getParent(); + if (ctx.hasAlias(parent)) + return ctx.getAlias(parent) + NAVIGATION + getLastSegment(); + return getParent().asProjection(ctx) + NAVIGATION + getLastSegment(); + } + + @Override + public String asExpression(AliasContext ctx) { + return getParent().asExpression(ctx) + NAVIGATION + getLastSegment(); + } + + /** + * A navigation path is joinable only when it represents domain of a + * subquery. + * @see QueryDefinitionImpl#addSubqueryRoot(PathExpression) + */ + @Override + public String asJoinable(AliasContext ctx) { + return asProjection(ctx) + " " + ctx.getAlias(this); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NewInstance.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NewInstance.java new file mode 100644 index 000000000..35bae7b44 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NewInstance.java @@ -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.query; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.persistence.OrderByItem; +import javax.persistence.SelectItem; + +/** + * Denotes NEW fully.qualified.class.name(arg1, arg2,...) + * + * @author Pinaki Poddar + * + */ +public class NewInstance implements Selectable { + private final Class _cls; + private List _args; + NewInstance(Class cls, SelectItem...args) { + _cls = cls; + if (args != null) { + _args = Arrays.asList(args); + } + } + + public OrderByItem asc() { + throw new UnsupportedOperationException(); + } + + public OrderByItem desc() { + throw new UnsupportedOperationException(); + } + + + public String asProjection(AliasContext ctx) { + StringBuffer tmp = new StringBuffer("NEW ").append(_cls.getName()) + .append("("); + if (_args == null || _args.isEmpty()) + return tmp.append(")").toString(); + int i = 0; + int N = _args.size(); + for (SelectItem arg : _args) { + i++; + tmp.append(((Selectable)arg).asProjection(ctx)) + .append(i == N ? ")" : ","); + } + return tmp.toString(); + } + + public void setAlias(AliasContext ctx) { + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NotEqualExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NotEqualExpression.java new file mode 100644 index 000000000..00f5ec97d --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/NotEqualExpression.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes (e1 != e2) Expression. + * + * @author Pinaki Poddar + * + */ +public class NotEqualExpression extends BinaryExpressionPredicate { + public NotEqualExpression(Expression op1, Expression op2) { + super(op1, BinaryConditionalOperator.EQUAL_NOT, + BinaryConditionalOperator.EQUAL, op2); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java new file mode 100644 index 000000000..3878bab43 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OperatorPath.java @@ -0,0 +1,58 @@ +/* + * 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.query; + +import org.apache.openjpa.util.InternalException; + +/** + * A path resulting from KEY() or VALUE() operation on an existing path. + * + * @author Pinaki Poddar + * + */ +public class OperatorPath extends AbstractDomainObject { + public OperatorPath(AbstractDomainObject operand, PathOperator operator) { + super(operand.getOwner(), operand, operator, null); + } + + @Override + public Class getLastSegment() { + throw new InternalException(); + } + + @Override + public String getAliasHint() { + return getParent().getAliasHint(); + } + + @Override + public String asProjection(AliasContext ctx) { + return getOperator() + "(" + getParent().asProjection(ctx) + ")"; + } + + @Override + public String asExpression(AliasContext ctx) { + return getOperator() + "(" + getParent().asExpression(ctx) + ")"; + } + + @Override + public String asJoinable(AliasContext ctx) { + throw new UnsupportedOperationException(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrPredicate.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrPredicate.java new file mode 100644 index 000000000..5b4ff3790 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrPredicate.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.Predicate; +import static org.apache.openjpa.persistence.query.ConditionalOperator.*; + +/** + * Denotes (e1 OR e2) predicate. + * + * @author Pinaki Poddar + * + */ +public class OrPredicate extends LogicalPredicate { + + public OrPredicate(Predicate p1, Predicate p2) { + super(p1, OR, AND, p2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrderableItem.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrderableItem.java new file mode 100644 index 000000000..1fa11aa6a --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/OrderableItem.java @@ -0,0 +1,47 @@ +/* + * 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.query; + +import javax.persistence.OrderByItem; + +/** + * Denotes an item of ORDER BY clause. + * + * @author Pinaki Poddar + * + */ +public class OrderableItem implements OrderByItem { + private final Boolean _asc; + private final ExpressionImpl path; + + OrderableItem(ExpressionImpl path) { + this(path, null); + } + + OrderableItem(ExpressionImpl path, Boolean asc) { + super(); + this._asc = asc; + this.path = path; + } + + public String toJPQL(AliasContext ctx) { + return path.asExpression(ctx) + " " + + (_asc == null ? "" : (_asc ? " ASC " : "DESC")); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ParameterExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ParameterExpression.java new file mode 100644 index 000000000..fb4f3c094 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ParameterExpression.java @@ -0,0 +1,36 @@ +/* + * 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.query; + +/** + * Denotes a parameter in a query. + * + * @author Pinaki Poddar + * + */ +public class ParameterExpression extends ConstantExpression { + public ParameterExpression(String name) { + super(name); + } + + @Override + public String asExpression(AliasContext ctx) { + return ":" + getValue(); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PathOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PathOperator.java new file mode 100644 index 000000000..c3d7e9af0 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PathOperator.java @@ -0,0 +1,48 @@ +/* + * 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.query; + +/** + * Operator that combines two components to form a path. + * + * @author Pinaki Poddar + * + */ +public enum PathOperator { + NONE(" "), + INNER(" JOIN "), + OUTER(" LEFT JOIN "), + FETCH_INNER(" JOIN FETCH "), + FETCH_OUTER(" LEFT JOIN FETCH "), + NAVIGATION("."), + KEY("KEY"), + ROOT(""), + VALUE("VALUE"), + ENTRY("ENTRY"); + + private final String _symbol; + + PathOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PlusExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PlusExpression.java new file mode 100644 index 000000000..c8921cbc8 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/PlusExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes (e1 + e2) Expression. + * + * @author Pinaki Poddar + * + */ +public class PlusExpression extends BinaryOperatorExpression { + public PlusExpression(Expression op, Expression op2) { + super(op, BinaryFunctionalOperator.PLUS, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java new file mode 100644 index 000000000..c72780471 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryBuilderImpl.java @@ -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.query; + +import javax.persistence.DomainObject; +import javax.persistence.PathExpression; +import javax.persistence.QueryBuilder; +import javax.persistence.QueryDefinition; + +/** + * The factory for QueryDefinition. + * + * + * @author Pinaki Poddar + * + */ +public class QueryBuilderImpl implements QueryBuilder { + /** + * Creates a QueryDefinition without a domain root. + */ + public QueryDefinition createQueryDefinition() { + return new QueryDefinitionImpl(this); + } + + /** + * Creates a QueryDefinition with given class as domain root. + */ + public DomainObject createQueryDefinition(Class root) { + return new QueryDefinitionImpl(this).addRoot(root); + } + + /** + * Creates a QueryDefinition that can be used as a subquery to some + * other query. + */ + public DomainObject createSubqueryDefinition(PathExpression path) { + return new QueryDefinitionImpl(this).addSubqueryRoot(path); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java new file mode 100644 index 000000000..faf75cf0f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryDefinitionImpl.java @@ -0,0 +1,425 @@ +/* + * 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.query; + +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.persistence.CaseExpression; +import javax.persistence.DomainObject; +import javax.persistence.Expression; +import javax.persistence.OrderByItem; +import javax.persistence.PathExpression; +import javax.persistence.Predicate; +import javax.persistence.QueryDefinition; +import javax.persistence.SelectItem; +import javax.persistence.Subquery; + +import org.apache.openjpa.lib.util.Localizer; + +/** + * Implements QueryDefinition. + * + * @author Pinaki Poddar + * + */ +public class QueryDefinitionImpl extends ExpressionImpl + implements QueryDefinition, Expression { + private final QueryBuilderImpl _builder; + private List _domains; + private List _groupBys; + private List _subqueries; + private List _orderBys; + private List _projections; + private boolean _distinct; + private Predicate _where; + private Predicate _having; + + protected static Localizer _loc = + Localizer.forPackage(QueryDefinitionImpl.class); + + protected QueryDefinitionImpl(QueryBuilderImpl builder) { + _builder = builder; + } + + /** + * Root domain object has no parent, no path but a non-null Class. + */ + public DomainObject addRoot(Class cls) { + RootPath root = new RootPath(this, cls); + addDomain(root); + return root; + } + + public DomainObject addSubqueryRoot(PathExpression path) { + if (_domains != null && _domains.contains(path)) + throw new IllegalArgumentException(_loc.get("query-subroot-clash", + path).toString()); + AbstractPath impl = (AbstractPath)path; + if (_subqueries == null) + _subqueries = new ArrayList(); + AbstractDomainObject newRoot = new NavigationPath(this, impl.getParent(), + impl.getLastSegment().toString()); + addDomain(newRoot); + return newRoot; + } + + protected void addDomain(AbstractDomainObject path) { + if (_domains == null) + _domains = new ArrayList(); + _domains.add(path); + } + + public Subquery all() { + return new AllExpression(this); + } + + public Subquery any() { + return new AnyExpression(this); + } + + public Expression coalesce(Expression... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(String... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(Date... exp) { + throw new UnsupportedOperationException(); + } + + public Expression coalesce(Calendar... exp) { + throw new UnsupportedOperationException(); + } + + public Expression currentDate() { + return new CurrentTimeExpression(Date.class); + } + + public Expression currentTime() { + return new CurrentTimeExpression(Time.class); + } + + public Expression currentTimestamp() { + return new CurrentTimeExpression(Timestamp.class); + } + + public Predicate exists() { + return new ExistsExpression(this); + } + + public CaseExpression generalCase() { + return new CaseExpressionImpl(); + } + + public QueryDefinition groupBy(PathExpression... pathExprs) { + if (_groupBys == null) { + _groupBys = new ArrayList(); + } + for (PathExpression e : pathExprs) + _groupBys.add(e); + return this; + } + + public QueryDefinition groupBy(List pathExprList) { + if (_groupBys == null) { + _groupBys = new ArrayList(); + } + for (PathExpression e : pathExprList) + _groupBys.add(e); + return this; + } + + public QueryDefinition having(Predicate predicate) { + _having = predicate; + return this; + } + + public Expression literal(String s) { + return new LiteralExpression(s); + } + + public Expression literal(Number n) { + return new LiteralExpression(n); + } + + public Expression literal(boolean b) { + return new LiteralExpression(b); + } + + public Expression literal(Calendar c) { + return new LiteralExpression(c); + } + + public Expression literal(Date d) { + return new LiteralExpression(d); + } + + public Expression literal(char c) { + return new LiteralExpression(c); + } + + public Expression literal(Class cls) { + return new LiteralExpression(cls); + } + + public Expression literal(Enum e) { + return new LiteralExpression(e); + } + + public Expression nullLiteral() { + return new LiteralExpression(null); + } + + public SelectItem newInstance(Class cls, SelectItem... args) { + return new NewInstance(cls, args); + } + + public Expression nullif(Expression exp1, Expression exp2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(Number arg1, Number arg2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(String arg1, String arg2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(Date arg1, Date arg2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(Calendar arg1, Calendar arg2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(Class arg1, Class arg2) { + throw new UnsupportedOperationException(); + } + + public Expression nullif(Enum arg1, Enum arg2) { + throw new UnsupportedOperationException(); + } + + public QueryDefinition orderBy(OrderByItem... orderByItems) { + if (_orderBys == null) + _orderBys = new ArrayList(); + for (OrderByItem i : orderByItems) { + if (i instanceof OrderableItem) + _orderBys.add((OrderableItem)i); + else + _orderBys.add(new OrderableItem((ExpressionImpl)i, null)); + } + return this; + } + + public QueryDefinition orderBy(List orderByItemList) { + if (_orderBys == null) + _orderBys = new ArrayList(); + for (OrderByItem i : orderByItemList) { + if (i instanceof OrderableItem) + _orderBys.add((OrderableItem)i); + else + _orderBys.add(new OrderableItem((ExpressionImpl)i, null)); + } + return this; + } + + public Expression param(String name) { + return new ParameterExpression(name); + } + + public Predicate predicate(boolean b) { + return null; + } + + public QueryDefinition select(SelectItem... items) { + return select(items == null ? null : Arrays.asList(items), false); + } + + public QueryDefinition select(List items) { + return select(items, false); + } + + public QueryDefinition selectDistinct(SelectItem... items) { + return select(items == null ? null : Arrays.asList(items), true); + } + + public QueryDefinition selectDistinct(List items) { + return select(items, false); + } + + private QueryDefinition select(List items, boolean isDistinct) { + if (_projections == null) { + _projections = new ArrayList(); + } else { + _projections.clear(); + } + _distinct = isDistinct; + for (SelectItem item : items) + _projections.add((Selectable)item); + return this; + } + + public CaseExpression simpleCase(Expression caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(Number caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(String caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(Date caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(Calendar caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(Class caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public CaseExpression simpleCase(Enum caseOperand) { + return new CaseExpressionImpl(caseOperand); + } + + public Subquery some() { + return new SomeExpression(this); + } + + public QueryDefinition where(Predicate predicate) { + _where = predicate; + return this; + } + + private List getProjections() { + if (_projections == null) { + List defaultProjection = new ArrayList(); + defaultProjection.add(_domains.get(0)); + return defaultProjection; + } + return _projections; + } + + public String toJPQL() { + return asExpression(new AliasContext()); + } + + /** + * + */ + @Override + public String asExpression(AliasContext ctx) { + StringBuffer buffer = new StringBuffer(); + registerDomains(ctx); + buffer.append("SELECT "); + if (_distinct) + buffer.append("DISTINCT "); + List projs = getProjections(); + for (int i=0; i < projs.size(); i++) { + projs.get(i).setAlias(ctx); + buffer.append(projs.get(i).asProjection(ctx)); + if (i != projs.size()-1) + buffer.append(","); + } + buffer.append(" FROM "); + for (int i=0; _domains != null && i < _domains.size(); i++) { + buffer.append(_domains.get(i).asJoinable(ctx)); + List joins = _domains.get(i).getJoins(); + if (joins != null) { + for (int j = 0; j < joins.size(); j++) { + buffer.append(joins.get(j).asJoinable(ctx)); + } + } + List fetchJoins = _domains.get(i).getFetchJoins(); + if (fetchJoins != null) { + for (int j = 0; j < fetchJoins.size(); j++) { + buffer.append(fetchJoins.get(j).asExpression(ctx)); + } + } + + if (i != _domains.size()-1) + buffer.append(","); + } + if (_where != null) { + buffer.append(" WHERE ").append(((Visitable)_where).asExpression(ctx)); + } + + if (_groupBys != null) { + buffer.append(" GROUP BY "); + for (int i = 0; i<_groupBys.size(); i++) { + buffer.append(((ExpressionImpl)_groupBys.get(i)).asExpression(ctx)); + if (i != _groupBys.size()-1) + buffer.append(","); + } + } + if (_having != null) { + buffer.append(" HAVING ").append(((Visitable)_having).asExpression(ctx)); + } + if (_orderBys != null) { + buffer.append(" ORDER BY "); + for (int i = 0; i<_orderBys.size(); i++) { + buffer.append(((OrderableItem)_orderBys.get(i)).toJPQL(ctx)); + if (i != _orderBys.size()-1) + buffer.append(","); + } + } + + return buffer.toString(); + } + + public String asProjection(AliasContext ctx) { + return asExpression(ctx); + } + + /** + * Registers each domain with an alias. + * @param ctx + */ + private void registerDomains(AliasContext ctx) { + if (_domains != null) { + for (AbstractDomainObject domain : _domains) { + domain.setAlias(ctx); + } + } + if (_subqueries != null) { + for (Subquery sub : _subqueries) { + if (sub instanceof QueryDefinitionImpl) + ((QueryDefinitionImpl)sub).registerDomains(ctx); + else + ((AbstractDomainObject)sub).setAlias(ctx); + } + } + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryExpression.java new file mode 100644 index 000000000..c4e0da4ef --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/QueryExpression.java @@ -0,0 +1,41 @@ +/* + * 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.query; + +import javax.persistence.Subquery; + +/** + * An expression resulting from operation on a query itself. Can be used as a + * subquery clause in a parent query. + * + * @author Pinaki Poddar + * + */ +abstract class QueryExpression extends UnaryOperatorExpression + implements Subquery { + public QueryExpression(QueryDefinitionImpl q, UnaryFunctionalOperator op) { + super(q, op); + } + + @Override + public String asExpression(AliasContext ctx) { + return "(" + super.asExpression(ctx) + ")"; + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RangeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RangeExpression.java new file mode 100644 index 000000000..d82ecf8aa --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RangeExpression.java @@ -0,0 +1,39 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes a range used by MEMBER OF operation. + * + * @author Pinaki Poddar + * + */ +public class RangeExpression extends BinaryOperatorExpression { + public RangeExpression(Expression e1, Expression e2) { + super(e1, BinaryFunctionalOperator.RANGE, e2); + } + + @Override + public String asExpression(AliasContext ctx) { + return "(" + ((Visitable)_e1).asExpression(ctx) + + " AND " + ((Visitable)_e2).asExpression(ctx) + ")"; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java new file mode 100644 index 000000000..b14a83859 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/RootPath.java @@ -0,0 +1,41 @@ +package org.apache.openjpa.persistence.query; + +import javax.persistence.DomainObject; + +/** + * Denotes root domain instance representing a persistent type. + * + * @author Pinaki Poddar + * + */ +public class RootPath extends AbstractDomainObject implements DomainObject { + + public RootPath(QueryDefinitionImpl owner, Class cls) { + super(owner, null, PathOperator.ROOT, cls); + } + + @Override + public Class getLastSegment() { + return (Class)super.getLastSegment(); + } + + @Override + public String getAliasHint() { + return getLastSegment().getSimpleName(); + } + + @Override + public String asExpression(AliasContext ctx) { + return ctx.getAlias(this); + } + + @Override + public String asJoinable(AliasContext ctx) { + return getLastSegment().getSimpleName() + " " + ctx.getAlias(this); + } + + @Override + public String asProjection(AliasContext ctx) { + return ctx.getAlias(this); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Selectable.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Selectable.java new file mode 100644 index 000000000..eb4e27df3 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Selectable.java @@ -0,0 +1,32 @@ +/* + * 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.query; + +import javax.persistence.SelectItem; + +/** + * An item that can be selected in a query. + * + * @author Pinaki Poddar + * + */ +public interface Selectable extends SelectItem { + String asProjection(AliasContext ctx); + void setAlias(AliasContext ctx); +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SizeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SizeExpression.java new file mode 100644 index 000000000..6e8b19d3f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SizeExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes SIZE(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class SizeExpression extends UnaryOperatorExpression { + public SizeExpression(Expression op) { + super(op, UnaryFunctionalOperator.SIZE); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SomeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SomeExpression.java new file mode 100644 index 000000000..689eb9c51 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SomeExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Subquery; + +/** + * Denotes SOME(Subquery) Expression. + * + * @author Pinaki Poddar + * + */ +class SomeExpression extends UnaryOperatorExpression implements Subquery { + public SomeExpression(QueryDefinitionImpl sub) { + super(sub, UnaryFunctionalOperator.SOME); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SquareRootExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SquareRootExpression.java new file mode 100644 index 000000000..b481d058f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SquareRootExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes SQRT(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class SquareRootExpression extends UnaryOperatorExpression { + public SquareRootExpression(Expression op) { + super(op, UnaryFunctionalOperator.SQRT); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SubStringExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SubStringExpression.java new file mode 100644 index 000000000..673e03a3e --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SubStringExpression.java @@ -0,0 +1,45 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes SUBSTR(a,i1,i2) Expression. + * + * @author Pinaki Poddar + * + */ +public class SubStringExpression extends BinaryOperatorExpression { + public SubStringExpression(Expression op, Expression op2) { + this(op, op2, new ConstantExpression(0)); + } + + public SubStringExpression(Expression op, int start) { + this(op, start, 0); + } + + public SubStringExpression(Expression op, int start, int len) { + this(op, new ConstantExpression(start), new ConstantExpression(len)); + } + + public SubStringExpression(Expression op, Expression op2, Expression pos) { + super(op, BinaryFunctionalOperator.SUBSTR, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SumExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SumExpression.java new file mode 100644 index 000000000..9f4d23e2c --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/SumExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes SUM(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class SumExpression extends UnaryOperatorExpression { + public SumExpression(Expression op) { + super(op, UnaryFunctionalOperator.SUM); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TimesExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TimesExpression.java new file mode 100644 index 000000000..3414bc9ee --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TimesExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes (e1*e2) Expression. + * + * @author Pinaki Poddar + * + */ +public class TimesExpression extends BinaryOperatorExpression { + public TimesExpression(Expression op1, Expression op2) { + super(op1, BinaryFunctionalOperator.TIMES, op2); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ToUpperExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ToUpperExpression.java new file mode 100644 index 000000000..e2bf2a926 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ToUpperExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes UPPER(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class ToUpperExpression extends UnaryOperatorExpression { + public ToUpperExpression(Expression op) { + super(op, UnaryFunctionalOperator.UPPER); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TrimExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TrimExpression.java new file mode 100644 index 000000000..bd5b06866 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TrimExpression.java @@ -0,0 +1,41 @@ +/* + * 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.query; + +import javax.persistence.Expression; +import javax.persistence.TrimSpec; + +/** + * Denotes TRIM(e1,x) Expression. + * + * @author Pinaki Poddar + * + */ +public class TrimExpression extends BinaryOperatorExpression { + TrimSpec _spec; + public TrimExpression(Expression op1, char ch, TrimSpec spec) { + super(op1, BinaryFunctionalOperator.TRIM, new ConstantExpression(ch)); + _spec = spec; + } + + public TrimExpression(Expression op, Expression op1, TrimSpec spec) { + super(op, BinaryFunctionalOperator.TRIM, op1); + _spec = spec; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TypeExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TypeExpression.java new file mode 100644 index 000000000..3869f72a1 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/TypeExpression.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes TYPE(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class TypeExpression extends UnaryOperatorExpression { + public TypeExpression(Expression op) { + super(op, UnaryFunctionalOperator.TYPE); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryConditionalOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryConditionalOperator.java new file mode 100644 index 000000000..36fe26a2d --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryConditionalOperator.java @@ -0,0 +1,49 @@ +/* + * 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.query; + +/** + * Enumeration of operator that operates on a single expression to generate + * a predicate. + * + * @see UnaryOperatorExpression + * + * @author Pinaki Poddar + * + */ +public enum UnaryConditionalOperator { + EXISTS("EXISTS"), + EXISTS_NOT("NOT EXISTS"), + + ISEMPTY("IS EMPTY"), + ISEMPTY_NOT("IS NOT EMPTY"), + ISNULL("IS NULL"), + ISNULL_NOT("IS NOT NULL"), + SOME("SOME"); + + private final String _symbol; + + UnaryConditionalOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryExpressionPredicate.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryExpressionPredicate.java new file mode 100644 index 000000000..1c2edfddc --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryExpressionPredicate.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.query; + +import javax.persistence.Expression; +import javax.persistence.Predicate; + +/** + * Unary Predicate results from an operator on an Expression. + * + * @author Pinaki Poddar + * + */ +class UnaryExpressionPredicate implements Predicate, Visitable { + protected final Expression _e; + protected final UnaryConditionalOperator _op; + private final UnaryConditionalOperator _nop; + + public UnaryExpressionPredicate(Expression e, UnaryConditionalOperator op, + UnaryConditionalOperator nop) { + this._e = e; + this._op = op; + this._nop = nop; + } + + public Expression getOperand() { + return _e; + } + + public UnaryConditionalOperator getOperator() { + return _op; + } + + public Predicate and(Predicate predicate) { + return new AndPredicate(this, predicate); + } + + public Predicate or(Predicate predicate) { + return new OrPredicate(this, predicate); + } + + public Predicate not() { + if (_nop == null) + throw new UnsupportedOperationException(this.toString()); + return new UnaryExpressionPredicate(_e, _nop, _op); + } + + public String asExpression(AliasContext ctx) { + return _op + "(" + ((ExpressionImpl)_e).asExpression(ctx) + ")"; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryFunctionalOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryFunctionalOperator.java new file mode 100644 index 000000000..34533d8e4 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryFunctionalOperator.java @@ -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.query; + +/** + * Enumeration of operator that operates on a single expression to generate + * another expression. + * + * @see UnaryOperatorExpression + * + * @author Pinaki Poddar + * + */ +public enum UnaryFunctionalOperator { + ABS("ABS"), + ALL("ALL"), + ANY("ANY"), + AVG("AVG"), + COUNT("COUNT"), + DISTINCT("DISTINCT"), + EXISTS("EXISTS"), + INDEX("INDEX"), + LENGTH("LENGTH"), + LOCATE("LOCATE"), + LOWER("TOLOWER"), + MAX("MAX"), + MIN("MIN"), + MINUS("-"), + SIZE("SIZE"), + SOME("SOME"), + SQRT("SQRT"), + SUM("SUM"), + TYPE("TYPE"), + UPPER("TOUPPER"); + + private final String _symbol; + + UnaryFunctionalOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryMinusExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryMinusExpression.java new file mode 100644 index 000000000..c8e0469c1 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryMinusExpression.java @@ -0,0 +1,35 @@ +/* + * 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.query; + +import javax.persistence.Expression; + +/** + * Denotes (-e) Expression. + * + * @author Pinaki Poddar + * + */ +public class UnaryMinusExpression extends UnaryOperatorExpression { + + public UnaryMinusExpression(Expression expr) { + super(expr, UnaryFunctionalOperator.MINUS); + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperator.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperator.java new file mode 100644 index 000000000..eaebe44bf --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperator.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.query; + +/** + * Enumeration of Operator that operate on a single expression. + * + * @author Pinaki Poddar + * + */ +public enum UnaryOperator { + ABS("ABS"), + ALL("ALL"), + ANY("ANY"), + AVG("AVG"), + COUNT("COUNT"), + DISTINCT("DISTINCT"), + EXISTS("EXISTS"), + INDEX("INDEX"), + ISEMPTY("IS EMPTY"), + ISEMPTY_NOT("IS NOT EMPTY"), + ISNULL("IS NULL"), + ISNULL_NOT("IS NOT NULL"), + LENGTH("LENGTH"), + LOCATE("LOCATE"), + LOWER("TOLOWER"), + MAX("MAX"), + MIN("MIN"), + MINUS("-"), + SIZE("SIZE"), + SOME("SOME"), + SQRT("SQRT"), + SUBSTRING("SUBSTR"), + SUM("SUM"), + TIMES("*"), + TRIM("TRIM"), + TYPE("TYPE"), + UPPER("TOUPPER"); + + private final String _symbol; + + UnaryOperator(String symbol) { + _symbol = symbol; + } + + public String toString() { + return _symbol; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperatorExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperatorExpression.java new file mode 100644 index 000000000..a857ab6d4 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/UnaryOperatorExpression.java @@ -0,0 +1,52 @@ +/* + * 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.query; + +import javax.persistence.Aggregate; +import javax.persistence.Expression; + +class UnaryOperatorExpression extends ExpressionImpl implements Aggregate { + protected final Expression _e; + protected final UnaryFunctionalOperator _op; + + public UnaryOperatorExpression(Expression e, UnaryFunctionalOperator op) { + _e = e; + _op = op; + } + + public Expression getOperand() { + return _e; + } + + public UnaryFunctionalOperator getOperator() { + return _op; + } + + public Expression distinct() { + return new DistinctExpression(this); + } + + public String asExpression(AliasContext ctx) { + return _op + "(" + ((Visitable)_e).asExpression(ctx) + ")"; + } + + public String asProjection(AliasContext ctx) { + return _op + "(" + ((Selectable)_e).asProjection(ctx) + ")"; + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ValueExpression.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ValueExpression.java new file mode 100644 index 000000000..cff7766d9 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/ValueExpression.java @@ -0,0 +1,31 @@ +/* + * 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.query; + +/** + * Denotes VALUE(e) Expression. + * + * @author Pinaki Poddar + * + */ +public class ValueExpression extends OperatorPath { + public ValueExpression(AbstractDomainObject expr) { + super(expr, PathOperator.VALUE); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java new file mode 100644 index 000000000..490cbb9fd --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/Visitable.java @@ -0,0 +1,33 @@ +/* + * 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.query; + +/** + * An element of query that is convertible to a JPQL String given a aliasing + * scheme. QueryDefinition visits each of its element and translates them. + * + * @author Pinaki Poddar + * + */ +public interface Visitable { + /** + * Get a JPQL fragment as used in a WHERE clause. + */ + String asExpression(AliasContext ctx); +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/WhenClause.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/WhenClause.java new file mode 100644 index 000000000..0e431702f --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/query/WhenClause.java @@ -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.query; + +/** + * Denotes WHEN ... THEN ... clause of a Case Statement. + * + * @author Pinaki Poddar + * + */ +public class WhenClause { + private final Object when; + private Object then; + + WhenClause(Object op) { + when = op; + } + + Object getThen() { + return then; + } + + void setThen(Object then) { + if (hasThen()) + throw new IllegalStateException("then() is already set"); + this.then = then; + } + + boolean hasThen() { + return then != null; + } + + public String toJPQL(AliasContext ctx) { + StringBuffer tmp = new StringBuffer(); + tmp.append(" WHEN ").append(JPQLHelper.toJPQL(ctx, when)) + .append(" THEN ").append(JPQLHelper.toJPQL(ctx, then)); + return tmp.toString(); + } +}