├── faces ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ ├── forge.xml │ │ │ └── beans.xml │ │ └── java │ │ └── com │ │ └── ctp │ │ └── cdi │ │ └── query │ │ └── home │ │ ├── FacesHome.java │ │ ├── FacesMessageObserver.java │ │ ├── FacesConversationProvider.java │ │ └── FacesNavigationProvider.java └── pom.xml ├── impl └── src │ ├── test │ ├── resources │ │ ├── test-settings.properties │ │ ├── logging.properties │ │ ├── test-default-orm.xml │ │ ├── test-orm.xml │ │ ├── test-custom-orm.xml │ │ └── log4j.xml │ ├── java │ │ └── com │ │ │ └── ctp │ │ │ └── cdi │ │ │ └── query │ │ │ ├── test │ │ │ ├── service │ │ │ │ ├── MyEntityDao.java │ │ │ │ ├── DaoInterface.java │ │ │ │ ├── MySimpleDao.java │ │ │ │ ├── ExtendedDaoInterface.java │ │ │ │ ├── MappedOneDao.java │ │ │ │ ├── Simple2Dao.java │ │ │ │ ├── HomeDao.java │ │ │ │ ├── SimpleQueryDslDao.java │ │ │ │ ├── SimpleEntityManagerDao.java │ │ │ │ ├── SimpleDaoWithEntityManager.java │ │ │ │ ├── Simplistic.java │ │ │ │ ├── MyEntityDaoDelegate.java │ │ │ │ ├── Statistics.java │ │ │ │ ├── SimpleDaoWithOverriddenEntityManager.java │ │ │ │ ├── HomeEntityHome.java │ │ │ │ ├── SimpleCriteriaDao.java │ │ │ │ └── SimpleDao.java │ │ │ ├── domain │ │ │ │ ├── mapped │ │ │ │ │ ├── MappedId.java │ │ │ │ │ ├── MappedSuperclass.java │ │ │ │ │ ├── MappedThree.java │ │ │ │ │ ├── MappedOne.java │ │ │ │ │ └── MappedTwo.java │ │ │ │ ├── OneToOne.java │ │ │ │ ├── OneToMany.java │ │ │ │ ├── EmbeddedSimple.java │ │ │ │ ├── Home.java │ │ │ │ ├── Simple3.java │ │ │ │ ├── Tee.java │ │ │ │ ├── Simple2.java │ │ │ │ ├── NamedEntity.java │ │ │ │ ├── Tee2.java │ │ │ │ ├── SimpleBuilder.java │ │ │ │ ├── Principal.java │ │ │ │ ├── Parent.java │ │ │ │ ├── TeeId.java │ │ │ │ └── AuditedEntity.java │ │ │ ├── util │ │ │ │ └── Logging.java │ │ │ └── TransactionalTestCase.java │ │ │ ├── handler │ │ │ ├── EntityManagerTestProducer.java │ │ │ ├── EntityManagerDaoHandlerTest.java │ │ │ └── EntityManagerTest.java │ │ │ ├── util │ │ │ └── EntityUtilsTest.java │ │ │ ├── meta │ │ │ ├── verifier │ │ │ │ └── EntityVerifierTest.java │ │ │ ├── extractor │ │ │ │ ├── TypeMetadataExtractorTest.java │ │ │ │ └── AnnotationMetadataExtractorTest.java │ │ │ └── unit │ │ │ │ └── OrmXmlBasedDaoTest.java │ │ │ ├── QueryExtensionTest.java │ │ │ ├── criteria │ │ │ └── QueryDslTest.java │ │ │ ├── spi │ │ │ └── CdiQuerySpiTest.java │ │ │ └── audit │ │ │ └── TimestampsProviderTest.java │ ├── resources-jbossas7 │ │ ├── test-persistence.xml │ │ ├── arquillian.xml │ │ └── test-mapped-persistence.xml │ ├── resources-openejb │ │ ├── arquillian.xml │ │ ├── jndi.properties │ │ ├── test-persistence.xml │ │ ├── META-INF │ │ │ ├── orm.xml │ │ │ ├── persistence.xml │ │ │ └── custom-orm.xml │ │ └── test-mapped-persistence.xml │ └── resources-glassfish │ │ ├── glassfish-resources.xml │ │ ├── test-persistence.xml │ │ ├── test-mapped-persistence.xml │ │ └── arquillian.xml │ ├── main │ ├── resources │ │ └── META-INF │ │ │ ├── services │ │ │ └── javax.enterprise.inject.spi.Extension │ │ │ └── beans.xml │ └── java │ │ └── com │ │ └── ctp │ │ └── cdi │ │ └── query │ │ ├── meta │ │ ├── verifier │ │ │ ├── Verifier.java │ │ │ └── EntityVerifier.java │ │ ├── extractor │ │ │ ├── MetadataExtractor.java │ │ │ ├── AnnotationMetadataExtractor.java │ │ │ └── TypeMetadataExtractor.java │ │ ├── unit │ │ │ ├── Descriptor.java │ │ │ ├── PersistenceUnit.java │ │ │ ├── MappedSuperclassDescriptor.java │ │ │ ├── EntityDescriptor.java │ │ │ ├── DescriptorHierarchyBuilder.java │ │ │ └── PersistenceUnits.java │ │ ├── MethodType.java │ │ ├── NonEntityException.java │ │ ├── DaoComponentsFactory.java │ │ ├── QueryInvocationLiteral.java │ │ ├── Initialized.java │ │ ├── QueryInvocation.java │ │ └── DaoEntity.java │ │ ├── audit │ │ ├── PreUpdateAuditListener.java │ │ ├── PrePersistAuditListener.java │ │ ├── AuditPropertyException.java │ │ ├── AuditProvider.java │ │ ├── AuditEntityListener.java │ │ └── PrincipalProvider.java │ │ ├── handler │ │ ├── QueryStringPostProcessor.java │ │ ├── JpaQueryPostProcessor.java │ │ ├── CdiQueryContextFactory.java │ │ ├── QueryDslSupportHandler.java │ │ ├── AbstractDelegateQueryHandler.java │ │ └── QueryInvocationException.java │ │ ├── util │ │ ├── jpa │ │ │ ├── QueryStringExtractor.java │ │ │ ├── ProviderSpecific.java │ │ │ ├── OpenJpaQueryStringExtractor.java │ │ │ ├── EclipseLinkEjbQueryStringExtractor.java │ │ │ ├── HibernateQueryStringExtractor.java │ │ │ ├── BaseQueryStringExtractor.java │ │ │ └── QueryStringExtractorFactory.java │ │ └── QueryUtils.java │ │ ├── builder │ │ ├── result │ │ │ ├── QueryProcessor.java │ │ │ └── QueryProcessorFactory.java │ │ ├── part │ │ │ ├── ConnectingQueryPart.java │ │ │ ├── AndQueryPart.java │ │ │ ├── OrQueryPart.java │ │ │ ├── QueryPart.java │ │ │ ├── BasePropertyQueryPart.java │ │ │ └── PropertyQueryPart.java │ │ ├── OrderDirection.java │ │ ├── WrappedQueryBuilder.java │ │ ├── postprocessor │ │ │ ├── MaxResultPostProcessor.java │ │ │ ├── FirstResultPostProcessor.java │ │ │ ├── LockModePostProcessor.java │ │ │ ├── FlushModePostProcessor.java │ │ │ ├── HintPostProcessor.java │ │ │ └── OrderByQueryStringPostProcessor.java │ │ ├── QueryBuilderContext.java │ │ ├── QueryBuilderFactory.java │ │ ├── MethodExpressionException.java │ │ ├── MethodQueryBuilder.java │ │ ├── QueryOperator.java │ │ └── AnnotatedQueryBuilder.java │ │ ├── criteria │ │ ├── processor │ │ │ ├── QueryProcessor.java │ │ │ └── OrderBy.java │ │ ├── predicate │ │ │ ├── NoValueBuilder.java │ │ │ ├── PredicateBuilder.java │ │ │ ├── SingleValueBuilder.java │ │ │ ├── IsNull.java │ │ │ ├── IsNotNull.java │ │ │ ├── Eq.java │ │ │ ├── NotEq.java │ │ │ ├── Like.java │ │ │ ├── LessThan.java │ │ │ ├── NotLike.java │ │ │ ├── GreaterThan.java │ │ │ ├── IsEmpty.java │ │ │ ├── IsNotEmpty.java │ │ │ ├── LessThanOrEqual.java │ │ │ ├── GreaterThanOrEqual.java │ │ │ ├── Between.java │ │ │ ├── OrBuilder.java │ │ │ ├── In.java │ │ │ └── FetchBuilder.java │ │ └── selection │ │ │ ├── SingularAttributeSelection.java │ │ │ ├── temporal │ │ │ ├── CurrentDate.java │ │ │ ├── CurrentTime.java │ │ │ └── CurrentTimestamp.java │ │ │ ├── AttributeQuerySelection.java │ │ │ ├── numeric │ │ │ ├── Abs.java │ │ │ ├── Max.java │ │ │ ├── Min.java │ │ │ ├── Neg.java │ │ │ ├── Sum.java │ │ │ ├── Avg.java │ │ │ ├── Count.java │ │ │ └── Modulo.java │ │ │ └── strings │ │ │ ├── Lower.java │ │ │ ├── Upper.java │ │ │ ├── SubstringFromTo.java │ │ │ └── SubstringFrom.java │ │ ├── home │ │ ├── DefaultConversationProvider.java │ │ ├── DefaultNavigationProvider.java │ │ └── QueryPersistenceUtils.java │ │ └── param │ │ ├── Parameter.java │ │ ├── NamedParameter.java │ │ └── IndexedParameter.java │ └── analysis │ └── resources │ ├── findbugs-exclusion.xml │ └── suppressions.xml ├── docs └── src │ └── main │ ├── style │ └── images │ │ ├── ctplogo.png │ │ ├── bkg_gradient.png │ │ ├── communitydoc.png │ │ └── CBbadge_builton_125.png │ ├── xslt │ ├── xhtml.xsl │ └── common.xsl │ ├── docbook │ └── en-US │ │ ├── query-general.xml │ │ ├── master.xml │ │ └── query-preface.xml │ └── assembly │ └── assembly.xml ├── api ├── src │ └── main │ │ └── java │ │ └── com │ │ └── ctp │ │ └── cdi │ │ └── query │ │ ├── criteria │ │ ├── QueryDslSupport.java │ │ └── QuerySelection.java │ │ ├── home │ │ ├── ConversationProvider.java │ │ ├── PersistenceUtils.java │ │ ├── NavigationProvider.java │ │ └── EntityMessage.java │ │ ├── NonEntity.java │ │ ├── audit │ │ ├── ModifiedBy.java │ │ ├── CreatedOn.java │ │ ├── ModifiedOn.java │ │ └── CurrentUser.java │ │ ├── FirstResult.java │ │ ├── MaxResults.java │ │ ├── QueryParam.java │ │ ├── Modifying.java │ │ ├── Dao.java │ │ ├── spi │ │ ├── DelegateQueryHandler.java │ │ └── QueryInvocationContext.java │ │ ├── WithEntityManager.java │ │ ├── AbstractEntityDao.java │ │ └── Query.java └── pom.xml ├── dist ├── src │ └── main │ │ └── assembly │ │ ├── notice.txt │ │ └── readme.txt └── pom.xml ├── README.md └── .gitignore /faces/src/main/resources/META-INF/forge.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /impl/src/test/resources/test-settings.properties: -------------------------------------------------------------------------------- 1 | arquillian.deploy.libs=${deploy.libs} 2 | -------------------------------------------------------------------------------- /impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension: -------------------------------------------------------------------------------- 1 | com.ctp.cdi.query.QueryExtension -------------------------------------------------------------------------------- /docs/src/main/style/images/ctplogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctpconsulting/query/HEAD/docs/src/main/style/images/ctplogo.png -------------------------------------------------------------------------------- /docs/src/main/style/images/bkg_gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctpconsulting/query/HEAD/docs/src/main/style/images/bkg_gradient.png -------------------------------------------------------------------------------- /docs/src/main/style/images/communitydoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctpconsulting/query/HEAD/docs/src/main/style/images/communitydoc.png -------------------------------------------------------------------------------- /docs/src/main/style/images/CBbadge_builton_125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctpconsulting/query/HEAD/docs/src/main/style/images/CBbadge_builton_125.png -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/verifier/Verifier.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.verifier; 2 | 3 | public interface Verifier { 4 | 5 | boolean verify(T t); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/PreUpdateAuditListener.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | public interface PreUpdateAuditListener { 4 | 5 | void preUpdate(Object entity); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/MyEntityDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | public interface MyEntityDao { 4 | 5 | E saveAndFlushAndRefresh(E entity); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/PrePersistAuditListener.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | public interface PrePersistAuditListener { 4 | 5 | void prePersist(Object entity); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/QueryStringPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | public interface QueryStringPostProcessor { 4 | 5 | String postProcess(String queryString); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/criteria/QueryDslSupport.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria; 2 | 3 | import com.mysema.query.jpa.impl.JPAQuery; 4 | 5 | public interface QueryDslSupport { 6 | 7 | JPAQuery jpaQuery(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /impl/src/analysis/resources/findbugs-exclusion.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/QueryStringExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import javax.persistence.Query; 4 | 5 | public interface QueryStringExtractor { 6 | 7 | String extractFrom(Query query); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/result/QueryProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.result; 2 | 3 | import javax.persistence.Query; 4 | 5 | public interface QueryProcessor { 6 | 7 | Object executeQuery(Query query); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/DaoInterface.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.test.domain.Simple; 5 | 6 | @Dao(Simple.class) 7 | public interface DaoInterface { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/JpaQueryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import javax.persistence.Query; 4 | 5 | public interface JpaQueryPostProcessor { 6 | 7 | Query postProcess(CdiQueryInvocationContext context, Query query); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /faces/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/home/ConversationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import java.io.Serializable; 4 | 5 | interface ConversationProvider extends Serializable { 6 | 7 | void begin(); 8 | 9 | void end(); 10 | 11 | boolean isTransient(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/home/PersistenceUtils.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import java.io.Serializable; 4 | 5 | interface PersistenceUtils extends Serializable { 6 | 7 | Class entityClass(Class homeClass); 8 | 9 | PK primaryKeyValue(E entity); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/mapped/MappedId.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain.mapped; 2 | 3 | public class MappedId { 4 | 5 | private Long id; 6 | 7 | public Long getId() { 8 | return id; 9 | } 10 | 11 | public void setId(Long id) { 12 | this.id = id; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/MySimpleDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.EntityDao; 5 | import com.ctp.cdi.query.test.domain.Simple; 6 | 7 | @Dao 8 | public interface MySimpleDao extends MyEntityDao, EntityDao { 9 | } 10 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/ExtendedDaoInterface.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.EntityDao; 5 | import com.ctp.cdi.query.test.domain.Simple; 6 | 7 | @Dao 8 | public interface ExtendedDaoInterface extends EntityDao { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/OneToOne.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | 5 | @Entity 6 | public class OneToOne extends NamedEntity { 7 | 8 | public OneToOne() { 9 | super(); 10 | } 11 | 12 | public OneToOne(String name) { 13 | super(name); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/MappedOneDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.AbstractEntityDao; 4 | import com.ctp.cdi.query.test.domain.mapped.MappedOne; 5 | 6 | public abstract class MappedOneDao extends AbstractEntityDao { 7 | 8 | public abstract MappedOne findByName(String name); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/Simple2Dao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.EntityDao; 5 | import com.ctp.cdi.query.test.domain.Simple2; 6 | 7 | @Dao 8 | public interface Simple2Dao extends EntityDao { 9 | 10 | Simple2 findByName(String name); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/home/NavigationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import java.io.Serializable; 4 | 5 | interface NavigationProvider extends Serializable { 6 | 7 | boolean isPostback(); 8 | 9 | Object create(); 10 | 11 | Object view(Object primaryKey); 12 | 13 | Object exception(); 14 | 15 | Object search(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/AuditPropertyException.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | public class AuditPropertyException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -8725707870578473975L; 6 | 7 | public AuditPropertyException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/OneToMany.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | 5 | @Entity 6 | public class OneToMany extends NamedEntity { 7 | 8 | public OneToMany() { 9 | super(); 10 | } 11 | 12 | public OneToMany(String name) { 13 | super(name); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/main/xslt/xhtml.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/mapped/MappedSuperclass.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain.mapped; 2 | 3 | public class MappedSuperclass extends MappedId { 4 | 5 | private Long counter; 6 | 7 | public Long getCounter() { 8 | return counter; 9 | } 10 | 11 | public void setCounter(Long id) { 12 | this.counter = id; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/mapped/MappedThree.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain.mapped; 2 | 3 | public class MappedThree extends MappedSuperclass { 4 | 5 | private String name; 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | 11 | public void setName(String name) { 12 | this.name = name; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/NonEntity.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | 4 | /** 5 | * Marker class to indicate that {@see Dao} doesn't have 6 | * particular entity class set. In such case it must 7 | * either implement {@see EntityDao} interface or extend 8 | * {@see AbstractEntityDao}. 9 | * 10 | * @author Bartosz Majsak 11 | * 12 | */ 13 | public class NonEntity { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/HomeDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.AbstractEntityDao; 4 | import com.ctp.cdi.query.QueryResult; 5 | import com.ctp.cdi.query.test.domain.Home; 6 | 7 | public abstract class HomeDao extends AbstractEntityDao { 8 | 9 | public abstract QueryResult findByName(String name); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleQueryDslDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.EntityDao; 5 | import com.ctp.cdi.query.criteria.QueryDslSupport; 6 | import com.ctp.cdi.query.test.domain.Simple; 7 | 8 | @Dao 9 | public abstract class SimpleQueryDslDao 10 | implements EntityDao, QueryDslSupport { 11 | } 12 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/processor/QueryProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.processor; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | 7 | public interface QueryProcessor

{ 8 | 9 | void process(CriteriaQuery query, CriteriaBuilder builder, Path

path); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/EmbeddedSimple.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Embeddable; 4 | 5 | @Embeddable 6 | public class EmbeddedSimple { 7 | 8 | private String embedd; 9 | 10 | public String getEmbedd() { 11 | return embedd; 12 | } 13 | 14 | public void setEmbedd(String embedd) { 15 | this.embedd = embedd; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/NoValueBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | 5 | abstract class NoValueBuilder implements PredicateBuilder { 6 | 7 | final SingularAttribute att; 8 | 9 | NoValueBuilder(SingularAttribute att) { 10 | this.att = att; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/PredicateBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.criteria.CriteriaBuilder; 6 | import javax.persistence.criteria.Path; 7 | import javax.persistence.criteria.Predicate; 8 | 9 | public interface PredicateBuilder

{ 10 | 11 | List build(CriteriaBuilder builder, Path

path); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/ProviderSpecific.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import static java.lang.annotation.ElementType.TYPE; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Target({ TYPE }) 10 | @Retention(RUNTIME) 11 | public @interface ProviderSpecific { 12 | 13 | String value(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleEntityManagerDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.EntityManager; 6 | 7 | import com.ctp.cdi.query.Dao; 8 | import com.ctp.cdi.query.test.domain.Simple3; 9 | 10 | @Dao(Simple3.class) 11 | public interface SimpleEntityManagerDao extends EntityManager { 12 | 13 | List findByName(String name); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/ConnectingQueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | /** 4 | * 5 | * @author thomashug 6 | */ 7 | abstract class ConnectingQueryPart extends QueryPart { 8 | 9 | protected final boolean first; 10 | 11 | public ConnectingQueryPart(boolean first) { 12 | this.first = first; 13 | } 14 | 15 | public boolean isFirst() { 16 | return first; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/OpenJpaQueryStringExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import javax.persistence.Query; 4 | 5 | @ProviderSpecific("org.apache.openjpa.persistence.OpenJPAQuery") 6 | public class OpenJpaQueryStringExtractor extends BaseQueryStringExtractor { 7 | 8 | @Override 9 | public String extractFrom(Query query) { 10 | return (String) invoke("getQueryString", query); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /impl/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/SingleValueBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | 5 | 6 | abstract class SingleValueBuilder extends NoValueBuilder { 7 | 8 | final V value; 9 | 10 | SingleValueBuilder(SingularAttribute att, V value) { 11 | super(att); 12 | this.value = value; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/criteria/QuerySelection.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | 8 | public interface QuerySelection { 9 | 10 | Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/OrderDirection.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | public enum OrderDirection { 4 | 5 | ASC { 6 | @Override 7 | public OrderDirection change() { 8 | return DESC; 9 | } 10 | }, 11 | DESC { 12 | @Override 13 | public OrderDirection change() { 14 | return ASC; 15 | } 16 | }; 17 | 18 | public abstract OrderDirection change(); 19 | } 20 | -------------------------------------------------------------------------------- /dist/src/main/assembly/notice.txt: -------------------------------------------------------------------------------- 1 | =================================================================================== 2 | == NOTICE file corresponding to section 4d of the Apache License, Version 2.0, == 3 | == in this case for the CDI Query distribution. == 4 | =================================================================================== 5 | 6 | CDI Query 7 | Copyright 2011 Cambridge Technology Partners, and individual contributors by the @authors tag 8 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/verifier/EntityVerifier.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.verifier; 2 | 3 | import javax.persistence.Entity; 4 | 5 | import com.ctp.cdi.query.meta.unit.PersistenceUnits; 6 | 7 | public class EntityVerifier implements Verifier> { 8 | 9 | @Override 10 | public boolean verify(Class entity) { 11 | return entity.isAnnotationPresent(Entity.class) || PersistenceUnits.instance().isEntity(entity); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/home/DefaultConversationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | public class DefaultConversationProvider implements ConversationProvider { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | @Override 8 | public void begin() { 9 | } 10 | 11 | @Override 12 | public void end() { 13 | } 14 | 15 | @Override 16 | public boolean isTransient() { 17 | return true; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/audit/ModifiedBy.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Marks a property which should keep track on the last changing user. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ElementType.FIELD, ElementType.METHOD}) 13 | public @interface ModifiedBy { 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/extractor/MetadataExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.extractor; 2 | 3 | import com.ctp.cdi.query.meta.DaoEntity; 4 | 5 | public interface MetadataExtractor { 6 | 7 | /** 8 | * Read entity meta data for a class. 9 | * @return Meta data packed in a {@link DaoEntity}, or {@code null} 10 | * if the extractor was not able to find data. 11 | */ 12 | DaoEntity extract(Class daoClass); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/FirstResult.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Use paging for the query. Must be applied to an Integer parameter. 10 | * @author thomashug 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.PARAMETER) 14 | public @interface FirstResult { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/MaxResults.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Limit the size of the result set. Must be applied to an Integer parameter. 10 | * @author thomashug 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.PARAMETER) 14 | public @interface MaxResults { 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/audit/CreatedOn.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Marks a property which should be updated with a timestamp when the entity gets persisted. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ElementType.FIELD, ElementType.METHOD}) 13 | public @interface CreatedOn { 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/param/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.param; 2 | 3 | import javax.persistence.Query; 4 | 5 | /** 6 | * Base class for parameters. 7 | * @author thomashug 8 | */ 9 | public abstract class Parameter { 10 | 11 | final Object value; 12 | final int argIndex; 13 | 14 | public Parameter(Object value, int argIndex) { 15 | this.value = value; 16 | this.argIndex = argIndex; 17 | } 18 | 19 | public abstract void apply(Query query); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /faces/src/main/java/com/ctp/cdi/query/home/FacesHome.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import static java.lang.annotation.ElementType.TYPE; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | import javax.enterprise.inject.Alternative; 10 | import javax.enterprise.inject.Stereotype; 11 | 12 | @Alternative 13 | @Stereotype 14 | @Target({ TYPE }) 15 | @Retention(RUNTIME) 16 | public @interface FacesHome { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/AuditProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import org.jboss.solder.logging.Logger; 4 | import org.jboss.solder.properties.Property; 5 | 6 | abstract class AuditProvider implements PrePersistAuditListener, PreUpdateAuditListener { 7 | 8 | final Logger log = Logger.getLogger(getClass()); 9 | 10 | String propertyName(Object entity, Property property) { 11 | return entity.getClass().getSimpleName() + "." + property.getName(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/CdiQueryContextFactory.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import javax.enterprise.context.RequestScoped; 4 | import javax.enterprise.event.Observes; 5 | import javax.enterprise.inject.Produces; 6 | 7 | @RequestScoped 8 | public class CdiQueryContextFactory { 9 | 10 | @Produces 11 | private CdiQueryInvocationContext context; 12 | 13 | public void contextCreated(@Observes CdiQueryInvocationContext context) { 14 | this.context = context; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/EclipseLinkEjbQueryStringExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import javax.persistence.Query; 4 | 5 | @ProviderSpecific("org.eclipse.persistence.jpa.JpaQuery") 6 | public class EclipseLinkEjbQueryStringExtractor extends BaseQueryStringExtractor { 7 | 8 | @Override 9 | public String extractFrom(Query query) { 10 | Object dbQuery = invoke("getDatabaseQuery", query); 11 | return (String) invoke("getJPQLString", dbQuery); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/HibernateQueryStringExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import javax.persistence.Query; 4 | 5 | @ProviderSpecific("org.hibernate.ejb.HibernateQuery") 6 | public class HibernateQueryStringExtractor extends BaseQueryStringExtractor { 7 | 8 | @Override 9 | public String extractFrom(Query query) { 10 | Object hibernateQuery = invoke("getHibernateQuery", query); 11 | return (String) invoke("getQueryString", hibernateQuery); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/handler/EntityManagerTestProducer.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import javax.enterprise.inject.Produces; 4 | import javax.persistence.EntityManager; 5 | import javax.persistence.PersistenceContext; 6 | 7 | import com.ctp.cdi.query.test.service.Simplistic; 8 | 9 | public class EntityManagerTestProducer { 10 | 11 | @SuppressWarnings("unused") 12 | @Produces @Simplistic 13 | @PersistenceContext 14 | private EntityManager entityManager; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /impl/src/test/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers=java.util.logging.ConsoleHandler 2 | .level=SEVERE 3 | 4 | java.util.logging.FileHandler.pattern=%h/java%u.log 5 | java.util.logging.FileHandler.limit=50000 6 | java.util.logging.FileHandler.count=1 7 | java.util.logging.FileHandler.formatter=java.util.logging.XMLFormatter 8 | 9 | java.util.logging.ConsoleHandler.level=ALL 10 | java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 11 | 12 | #org.glassfish.level=SEVERE 13 | #com.sun.enterprise.level=INFO 14 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleDaoWithEntityManager.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import com.ctp.cdi.query.Dao; 6 | import com.ctp.cdi.query.EntityDao; 7 | import com.ctp.cdi.query.WithEntityManager; 8 | import com.ctp.cdi.query.test.domain.Simple; 9 | 10 | @Dao 11 | @WithEntityManager(Simplistic.class) 12 | public interface SimpleDaoWithEntityManager extends EntityDao { 13 | 14 | List findByName(String name); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/BaseQueryStringExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public abstract class BaseQueryStringExtractor implements QueryStringExtractor { 6 | 7 | Object invoke(String methodName, Object target) { 8 | try { 9 | Method method = target.getClass().getMethod(methodName); 10 | return method.invoke(target); 11 | } catch (Exception e) { 12 | throw new RuntimeException(e); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/SingularAttributeSelection.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | 5 | import com.ctp.cdi.query.criteria.QuerySelection; 6 | 7 | public abstract class SingularAttributeSelection implements QuerySelection { 8 | 9 | protected final SingularAttribute attribute; 10 | 11 | public SingularAttributeSelection(SingularAttribute attribute) { 12 | this.attribute = attribute; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/QueryParam.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Mark a method parameter as a query parameter. 10 | * Can be named by the annotation value. 11 | * 12 | * @author thomashug 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.PARAMETER) 16 | public @interface QueryParam { 17 | String value() default ""; 18 | } 19 | -------------------------------------------------------------------------------- /docs/src/main/docbook/en-US/query-general.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | CDI Query Module 7 | Reference Guide 8 | 1.0.0.Alpha5 9 | 10 | 11 | 12 | Thomas 13 | Hug 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /impl/src/analysis/resources/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/QueryDslSupportHandler.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import org.jboss.solder.core.Requires; 4 | 5 | import com.ctp.cdi.query.criteria.QueryDslSupport; 6 | import com.mysema.query.jpa.impl.JPAQuery; 7 | 8 | @Requires("com.mysema.query.jpa.impl.JPAQuery") 9 | public class QueryDslSupportHandler extends AbstractDelegateQueryHandler 10 | implements QueryDslSupport { 11 | 12 | @Override 13 | public JPAQuery jpaQuery() { 14 | return new JPAQuery(getEntityManager()); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/Descriptor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import java.net.URL; 4 | 5 | import org.w3c.dom.Document; 6 | 7 | class Descriptor { 8 | 9 | private final Document document; 10 | private final URL url; 11 | 12 | public Descriptor(Document document, URL url) { 13 | this.document = document; 14 | this.url = url; 15 | } 16 | 17 | public Document getDocument() { 18 | return document; 19 | } 20 | 21 | public URL getUrl() { 22 | return url; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Home.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Home { 9 | 10 | @Id @GeneratedValue 11 | private Long id; 12 | 13 | private String name; 14 | 15 | public Long getId() { 16 | return id; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/param/NamedParameter.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.param; 2 | 3 | import javax.persistence.Query; 4 | 5 | /** 6 | * Parameters which have a name (:name). 7 | * @author thomashug 8 | */ 9 | public class NamedParameter extends Parameter { 10 | 11 | private final String name; 12 | 13 | public NamedParameter(String name, Object value, int argIndex) { 14 | super(value, argIndex); 15 | this.name = name; 16 | } 17 | 18 | @Override 19 | public void apply(Query query) { 20 | query.setParameter(name, value); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Simple3.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Simple3 { 9 | 10 | @GeneratedValue @Id 11 | private long id; 12 | 13 | private String name; 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public long getId() { 24 | return id; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/MethodType.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | /** 4 | * DAO method type. Stands for 5 | *
    6 | *
  • Delegated methods - the DAO has a concrete implementation for this 7 | * or the method is implemented in the {@link EntityDaoHandler}.
  • 8 | *
  • Annotated method - the query is defined via a Query annotation.
  • 9 | *
  • The method defines a query expression by its name.
  • 10 | *
11 | * 12 | * @author thomashug 13 | */ 14 | public enum MethodType { 15 | 16 | DELEGATE, ANNOTATED, PARSE 17 | 18 | } 19 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/param/IndexedParameter.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.param; 2 | 3 | import javax.persistence.Query; 4 | 5 | /** 6 | * Query parameters which have an index (?1). 7 | * @author thomashug 8 | */ 9 | public class IndexedParameter extends Parameter { 10 | 11 | private final int index; 12 | 13 | public IndexedParameter(int index, Object value, int argIndex) { 14 | super(value, argIndex); 15 | this.index = index; 16 | } 17 | 18 | @Override 19 | public void apply(Query query) { 20 | query.setParameter(index, value); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/test/resources-jbossas7/test-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | java:jboss/datasources/ExampleDS 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /faces/src/main/java/com/ctp/cdi/query/home/FacesMessageObserver.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import javax.enterprise.event.Observes; 4 | import javax.enterprise.inject.Alternative; 5 | import javax.faces.application.FacesMessage; 6 | import javax.faces.context.FacesContext; 7 | 8 | @Alternative 9 | public class FacesMessageObserver { 10 | 11 | public void observe(@Observes EntityMessage message) { 12 | if (message.isFailure()) { 13 | FacesContext.getCurrentInstance().addMessage(null, 14 | new FacesMessage(message.getException().getMessage())); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/NonEntityException.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | public class NonEntityException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 7196572996969471161L; 6 | 7 | public NonEntityException() { 8 | super(); 9 | } 10 | 11 | public NonEntityException(String message) { 12 | super(message); 13 | } 14 | 15 | public NonEntityException(Throwable cause) { 16 | super(cause); 17 | } 18 | 19 | public NonEntityException(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/Modifying.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import javax.persistence.Query; 9 | 10 | /** 11 | * Marks a query method to be modifying. This will execute the {@link Query#executeUpdate()} 12 | * method instead of {@link Query#getResultList()} (or the corresponding single result method). 13 | * 14 | * @author thomashug 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.METHOD) 18 | public @interface Modifying { 19 | } 20 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/WrappedQueryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | import com.ctp.cdi.query.builder.result.DefaultQueryResult; 4 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 5 | 6 | public class WrappedQueryBuilder extends QueryBuilder { 7 | 8 | private final QueryBuilder delegate; 9 | 10 | public WrappedQueryBuilder(QueryBuilder delegate) { 11 | this.delegate = delegate; 12 | } 13 | 14 | @Override 15 | @SuppressWarnings("rawtypes") 16 | public Object execute(CdiQueryInvocationContext ctx) { 17 | return new DefaultQueryResult(delegate, ctx); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /impl/src/test/resources/test-default-orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.ctp.cdi.query.test.domain.mapped 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/Dao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Inherited; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * The Dao annotation needs to be present in order to have the 11 | * interface or class to be processed by the CDI extension. 12 | * 13 | * @author thomashug 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(ElementType.TYPE) 17 | @Inherited 18 | public @interface Dao { 19 | Class value() default NonEntity.class; 20 | } 21 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/AbstractDelegateQueryHandler.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import javax.inject.Inject; 4 | import javax.persistence.EntityManager; 5 | 6 | import com.ctp.cdi.query.spi.DelegateQueryHandler; 7 | 8 | public abstract class AbstractDelegateQueryHandler implements DelegateQueryHandler { 9 | 10 | @Inject 11 | protected CdiQueryInvocationContext context; 12 | 13 | protected Class getEntityClass() { 14 | return (Class) context.getEntityClass(); 15 | } 16 | 17 | protected EntityManager getEntityManager() { 18 | return context.getEntityManager(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/audit/ModifiedOn.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Marks a property which should be updated with a timestamp when the entity gets updated. 10 | * By settings {@link #onCreate()} to {@code true}, the property gets also set when 11 | * the entity is persisted. 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target({ElementType.FIELD, ElementType.METHOD}) 15 | public @interface ModifiedOn { 16 | boolean onCreate() default false; 17 | } -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/mapped/MappedOne.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain.mapped; 2 | 3 | public class MappedOne { 4 | 5 | private Long id; 6 | private String name; 7 | 8 | public MappedOne() { } 9 | 10 | public MappedOne(String name) { 11 | this.name = name; 12 | } 13 | 14 | public Long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/DaoComponentsFactory.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | import javax.enterprise.inject.Produces; 4 | 5 | /** 6 | * DAO components producer. Exposes a singleton both programmatically 7 | * as well as over a CDI producer. 8 | * 9 | * @author thomashug 10 | */ 11 | public class DaoComponentsFactory { 12 | 13 | private static DaoComponents components = new DaoComponents(); 14 | 15 | public static DaoComponents instance() { 16 | return components; 17 | } 18 | 19 | @Produces @Initialized 20 | public DaoComponents producer() { 21 | return instance(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/util/Logging.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.util; 2 | 3 | import java.io.InputStream; 4 | import java.util.logging.LogManager; 5 | 6 | public class Logging { 7 | 8 | private Logging() { 9 | } 10 | 11 | public static void reconfigure() { 12 | try { 13 | InputStream loggingProperties = Logging.class.getClassLoader().getResourceAsStream("logging.properties"); 14 | LogManager.getLogManager().readConfiguration(loggingProperties); 15 | } catch (Exception e) { 16 | throw new RuntimeException("Failed to reconfigure Java Logging.", e); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /impl/src/test/resources/test-orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/MaxResultPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.Query; 4 | 5 | import com.ctp.cdi.query.handler.JpaQueryPostProcessor; 6 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 7 | 8 | public class MaxResultPostProcessor implements JpaQueryPostProcessor { 9 | 10 | private final int max; 11 | 12 | public MaxResultPostProcessor(int max) { 13 | this.max = max; 14 | } 15 | 16 | @Override 17 | public Query postProcess(CdiQueryInvocationContext context, Query query) { 18 | query.setMaxResults(max); 19 | return query; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/temporal/CurrentDate.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.temporal; 2 | 3 | import java.sql.Date; 4 | 5 | import javax.persistence.criteria.CriteriaBuilder; 6 | import javax.persistence.criteria.CriteriaQuery; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Selection; 9 | 10 | import com.ctp.cdi.query.criteria.QuerySelection; 11 | 12 | public class CurrentDate

implements QuerySelection { 13 | 14 | @Override 15 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 16 | return builder.currentDate(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/temporal/CurrentTime.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.temporal; 2 | 3 | import java.sql.Time; 4 | 5 | import javax.persistence.criteria.CriteriaBuilder; 6 | import javax.persistence.criteria.CriteriaQuery; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Selection; 9 | 10 | import com.ctp.cdi.query.criteria.QuerySelection; 11 | 12 | public class CurrentTime

implements QuerySelection { 13 | 14 | @Override 15 | public Selection

implements QuerySelection { 13 | 14 | @Override 15 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 16 | return builder.currentTimestamp(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Tee.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.EmbeddedId; 6 | import javax.persistence.Entity; 7 | 8 | @Entity 9 | @SuppressWarnings("serial") 10 | public class Tee implements Serializable { 11 | 12 | @EmbeddedId 13 | private TeeId id; 14 | private int distance; 15 | 16 | public TeeId getId() { 17 | return id; 18 | } 19 | 20 | public void setId(TeeId id) { 21 | this.id = id; 22 | } 23 | 24 | public int getDistance() { 25 | return distance; 26 | } 27 | 28 | public void setDistance(int distance) { 29 | this.distance = distance; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /faces/src/main/java/com/ctp/cdi/query/home/FacesConversationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import javax.enterprise.context.Conversation; 4 | import javax.inject.Inject; 5 | 6 | @FacesHome 7 | public class FacesConversationProvider implements ConversationProvider { 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | @Inject 12 | private Conversation conversation; 13 | 14 | @Override 15 | public void begin() { 16 | conversation.begin(); 17 | } 18 | 19 | @Override 20 | public void end() { 21 | conversation.end(); 22 | } 23 | 24 | @Override 25 | public boolean isTransient() { 26 | return conversation.isTransient(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/home/DefaultNavigationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | public class DefaultNavigationProvider implements NavigationProvider { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | @Override 8 | public Object create() { 9 | return null; 10 | } 11 | 12 | @Override 13 | public boolean isPostback() { 14 | return false; 15 | } 16 | 17 | @Override 18 | public Object view(Object primaryKey) { 19 | return null; 20 | } 21 | 22 | @Override 23 | public Object exception() { 24 | return null; 25 | } 26 | 27 | @Override 28 | public Object search() { 29 | return null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/arquillian.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/Simplistic.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.METHOD; 5 | import static java.lang.annotation.ElementType.PARAMETER; 6 | import static java.lang.annotation.ElementType.TYPE; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | import java.lang.annotation.Documented; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.Target; 12 | 13 | import javax.inject.Qualifier; 14 | 15 | @Qualifier 16 | @Target({ TYPE, METHOD, PARAMETER, FIELD }) 17 | @Retention(RUNTIME) 18 | @Documented 19 | public @interface Simplistic { 20 | } 21 | -------------------------------------------------------------------------------- /impl/src/test/resources-jbossas7/arquillian.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -Xms64m -Xmx1024m -XX:MaxPermSize=512m 13 | target/jboss-as-7.1.1.Final 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /impl/src/test/resources-jbossas7/test-mapped-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | java:jboss/datasources/ExampleDS 5 | META-INF/orm.xml 6 | META-INF/custom-orm.xml 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/FirstResultPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.Query; 4 | 5 | import com.ctp.cdi.query.handler.JpaQueryPostProcessor; 6 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 7 | 8 | public class FirstResultPostProcessor implements JpaQueryPostProcessor { 9 | 10 | private final int startPosition; 11 | 12 | public FirstResultPostProcessor(int startPosition) { 13 | this.startPosition = startPosition; 14 | } 15 | 16 | @Override 17 | public Query postProcess(CdiQueryInvocationContext context, Query query) { 18 | query.setFirstResult(startPosition); 19 | return query; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/IsNull.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | public class IsNull extends NoValueBuilder { 12 | 13 | public IsNull(SingularAttribute att) { 14 | super(att); 15 | } 16 | 17 | @Override 18 | public List build(CriteriaBuilder builder, Path path) { 19 | return Arrays.asList(builder.isNull(path.get(att))); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/IsNotNull.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | public class IsNotNull extends NoValueBuilder { 12 | 13 | public IsNotNull(SingularAttribute att) { 14 | super(att); 15 | } 16 | 17 | @Override 18 | public List build(CriteriaBuilder builder, Path path) { 19 | return Arrays.asList(builder.isNotNull(path.get(att))); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /docs/src/main/assembly/assembly.xml: -------------------------------------------------------------------------------- 1 | 5 | sources 6 | 7 | zip 8 | 9 | ${project.artifactId} 10 | 11 | 12 | . 13 | ${project.basedir}/src/main/docbook/en-US 14 | true 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/Eq.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class Eq extends SingleValueBuilder { 13 | 14 | public Eq(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.equal(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Simple2.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Simple2 { 9 | 10 | @Id 11 | @GeneratedValue 12 | private Long id; 13 | 14 | private String name; 15 | 16 | public Simple2() { 17 | } 18 | 19 | public Simple2(String name) { 20 | this.name = name; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public Long getId() { 32 | return id; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/LockModePostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.LockModeType; 4 | import javax.persistence.Query; 5 | 6 | import com.ctp.cdi.query.handler.JpaQueryPostProcessor; 7 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 8 | 9 | public class LockModePostProcessor implements JpaQueryPostProcessor { 10 | 11 | private final LockModeType lockMode; 12 | 13 | public LockModePostProcessor(LockModeType lockMode) { 14 | this.lockMode = lockMode; 15 | } 16 | 17 | @Override 18 | public Query postProcess(CdiQueryInvocationContext context, Query query) { 19 | query.setLockMode(lockMode); 20 | return query; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/home/QueryPersistenceUtils.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import com.ctp.cdi.query.meta.extractor.TypeMetadataExtractor; 4 | import com.ctp.cdi.query.util.EntityUtils; 5 | 6 | public class QueryPersistenceUtils implements PersistenceUtils { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | @Override 11 | @SuppressWarnings("unchecked") 12 | public Class entityClass(Class homeClass) { 13 | return (Class) new TypeMetadataExtractor().extract(homeClass).getEntityClass(); 14 | } 15 | 16 | @Override 17 | @SuppressWarnings("unchecked") 18 | public PK primaryKeyValue(Object entity) { 19 | return (PK) EntityUtils.primaryKeyValue(entity); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/mapped/MappedTwo.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain.mapped; 2 | 3 | 4 | public class MappedTwo { 5 | 6 | private Long teeSetId; 7 | private Long holeId; 8 | 9 | private String name; 10 | 11 | public Long getTeeSetId() { 12 | return teeSetId; 13 | } 14 | 15 | public void setTeeSetId(Long teeSetId) { 16 | this.teeSetId = teeSetId; 17 | } 18 | 19 | public Long getHoleId() { 20 | return holeId; 21 | } 22 | 23 | public void setHoleId(Long holeId) { 24 | this.holeId = holeId; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/FlushModePostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.FlushModeType; 4 | import javax.persistence.Query; 5 | 6 | import com.ctp.cdi.query.handler.JpaQueryPostProcessor; 7 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 8 | 9 | public class FlushModePostProcessor implements JpaQueryPostProcessor { 10 | 11 | private final FlushModeType flushMode; 12 | 13 | public FlushModePostProcessor(FlushModeType flushMode) { 14 | this.flushMode = flushMode; 15 | } 16 | 17 | @Override 18 | public Query postProcess(CdiQueryInvocationContext context, Query query) { 19 | query.setFlushMode(flushMode); 20 | return query; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/NotEq.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class NotEq extends SingleValueBuilder { 13 | 14 | public NotEq(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.notEqual(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/jndi.properties: -------------------------------------------------------------------------------- 1 | # initial context factory 2 | java.naming.factory.initial = org.apache.openejb.client.LocalInitialContextFactory 3 | 4 | # logging 5 | log4j.category.OpenEJB.options = debug 6 | log4j.category.OpenEJB.startup = debug 7 | log4j.category.OpenEJB.startup.config = debug 8 | 9 | # resources 10 | testDatabase = new://Resource?type=DataSource 11 | testDatabase.JdbcDriver = org.hsqldb.jdbcDriver 12 | testDatabase.JdbcUrl = jdbc:hsqldb:mem:testdb 13 | testDatabase.JtaManaged = true 14 | 15 | test.hibernate.dialect = org.hibernate.dialect.HSQLDialect 16 | 17 | # openejb flags 18 | openejb.descriptors.output = true 19 | openejb.validation.output.level = verbose 20 | openejb.autocreate.jta-datasource-from-non-jta-one = true 21 | openejb.servicemanager.enabled = true -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/QueryBuilderContext.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | /** 4 | * 5 | * @author thomashug 6 | */ 7 | public class QueryBuilderContext { 8 | 9 | private final StringBuilder builder; 10 | private int counter = 1; 11 | 12 | public QueryBuilderContext() { 13 | this.builder = new StringBuilder(); 14 | } 15 | 16 | public int increment() { 17 | return counter++; 18 | } 19 | 20 | public QueryBuilderContext append(String string) { 21 | builder.append(string); 22 | return this; 23 | } 24 | 25 | public String resultString() { 26 | return builder.toString(); 27 | } 28 | 29 | public int getCounter() { 30 | return counter; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/Like.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class Like extends SingleValueBuilder { 13 | 14 | public Like(SingularAttribute att, String value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.like(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/LessThan.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class LessThan extends SingleValueBuilder { 13 | 14 | public LessThan(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.lt(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/NotLike.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class NotLike extends SingleValueBuilder { 13 | 14 | public NotLike(SingularAttribute att, String value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.notLike(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/audit/CurrentUser.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.METHOD; 5 | import static java.lang.annotation.ElementType.PARAMETER; 6 | import static java.lang.annotation.ElementType.TYPE; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | import java.lang.annotation.Documented; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.Target; 12 | 13 | import javax.inject.Qualifier; 14 | 15 | /** 16 | * Identifies the current user responsible for entity creation or modification. 17 | */ 18 | @Qualifier 19 | @Target({ TYPE, METHOD, PARAMETER, FIELD }) 20 | @Retention(RUNTIME) 21 | @Documented 22 | public @interface CurrentUser { 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/spi/DelegateQueryHandler.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.spi; 2 | 3 | 4 | 5 | /** 6 | * A marker interface. Used for writing custom query methods: 7 | * 8 | * public interface DaoExtension { 9 | * E saveAndFlushAndRefresh(E entity); 10 | * } 11 | * 12 | * public class DelegateDaoExtension implements DaoExtension, DelegateQueryHandler { 13 | * @Inject 14 | * private QueryInvocationContext context; 15 | * 16 | * @Override 17 | * public E saveAndFlushAndRefresh(E entity) { 18 | * ... 19 | * } 20 | * } 21 | * 22 | * The extension is now usable with: 23 | * 24 | * @Dao 25 | * public interface MySimpleDao extends DaoExtension, EntityDao { 26 | * } 27 | * 28 | */ 29 | public interface DelegateQueryHandler { 30 | } 31 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/AttributeQuerySelection.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | 10 | public class AttributeQuerySelection extends SingularAttributeSelection { 11 | 12 | public AttributeQuerySelection(SingularAttribute attribute) { 13 | super(attribute); 14 | } 15 | 16 | @Override 17 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 18 | return path.get(attribute); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/NamedEntity.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.GeneratedValue; 4 | import javax.persistence.Id; 5 | import javax.persistence.MappedSuperclass; 6 | 7 | @MappedSuperclass 8 | public class NamedEntity { 9 | 10 | @Id 11 | @GeneratedValue 12 | private Long id; 13 | 14 | private String name; 15 | 16 | public NamedEntity() { 17 | } 18 | 19 | public NamedEntity(String name) { 20 | this.name = name; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public Long getId() { 32 | return id; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/HintPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.Query; 4 | 5 | import com.ctp.cdi.query.handler.JpaQueryPostProcessor; 6 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 7 | 8 | public class HintPostProcessor implements JpaQueryPostProcessor { 9 | 10 | private final String hintName; 11 | private final Object hintValue; 12 | 13 | public HintPostProcessor(String hintName, Object hintValue) { 14 | this.hintName = hintName; 15 | this.hintValue = hintValue; 16 | } 17 | 18 | @Override 19 | public Query postProcess(CdiQueryInvocationContext context, Query query) { 20 | query.setHint(hintName, hintValue); 21 | return query; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/GreaterThan.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class GreaterThan extends SingleValueBuilder { 13 | 14 | public GreaterThan(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.gt(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/IsEmpty.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import javax.persistence.criteria.CriteriaBuilder; 8 | import javax.persistence.criteria.Path; 9 | import javax.persistence.criteria.Predicate; 10 | import javax.persistence.metamodel.SingularAttribute; 11 | 12 | public class IsEmpty> extends NoValueBuilder { 13 | 14 | public IsEmpty(SingularAttribute att) { 15 | super(att); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.isEmpty(path.get(att))); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/test/resources-glassfish/glassfish-resources.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.classpath 3 | /.settings/ 4 | /.idea/ 5 | /cdi-query-parent.iml 6 | /checkstyle-cachefile 7 | /target/ 8 | /docs/target/ 9 | /impl/.classpath 10 | /impl/.project 11 | /impl/cdi-query-impl.iml 12 | /impl/.pmd 13 | /impl/.checkstyle 14 | /impl/.settings/ 15 | /impl/derby.log 16 | /docs/.project 17 | /docs/.settings/ 18 | /dist/.project 19 | /dist/.settings/ 20 | /dist/target/ 21 | /combined/.project 22 | /combined/.settings/ 23 | /api/.classpath 24 | /api/.project 25 | /api/.settings/ 26 | /api/cdi-query-api.iml 27 | /api/target/ 28 | /combined/target/ 29 | /impl/target/ 30 | /combined/.classpath 31 | /docs/.classpath 32 | /api/nb-configuration.xml 33 | /checkstyle-cachefile 34 | .DS_Store 35 | .externalToolBuilders 36 | /faces/target/ 37 | /faces/.classpath 38 | /faces/.project 39 | /faces/.settings/ 40 | 41 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/QueryInvocationLiteral.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | import javax.enterprise.util.AnnotationLiteral; 4 | 5 | /** 6 | * Utility class to construct a qualifier and resolve a dependency programmatically. 7 | * 8 | * @author thomashug 9 | */ 10 | @SuppressWarnings("all") 11 | public class QueryInvocationLiteral extends AnnotationLiteral 12 | implements QueryInvocation { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | private final MethodType methodType; 17 | 18 | public QueryInvocationLiteral(MethodType methodType) { 19 | this.methodType = methodType; 20 | } 21 | 22 | @Override 23 | public MethodType value() { 24 | return methodType; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/IsNotEmpty.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import javax.persistence.criteria.CriteriaBuilder; 8 | import javax.persistence.criteria.Path; 9 | import javax.persistence.criteria.Predicate; 10 | import javax.persistence.metamodel.SingularAttribute; 11 | 12 | public class IsNotEmpty> extends NoValueBuilder { 13 | 14 | public IsNotEmpty(SingularAttribute att) { 15 | super(att); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.isNotEmpty(path.get(att))); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/WithEntityManager.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import static java.lang.annotation.ElementType.TYPE; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Annotation; 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Inherited; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | * Use this annotation when not using the default entity manager. If there are more than one, 14 | * CDI Query needs to know which one to use for a specific DAO. 15 | * 16 | * @author thomashug 17 | */ 18 | @Target(TYPE) 19 | @Retention(RUNTIME) 20 | @Documented 21 | @Inherited 22 | public @interface WithEntityManager { 23 | Class[] value(); 24 | } 25 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/MyEntityDaoDelegate.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import javax.inject.Inject; 4 | import javax.persistence.EntityManager; 5 | 6 | import com.ctp.cdi.query.spi.DelegateQueryHandler; 7 | import com.ctp.cdi.query.spi.QueryInvocationContext; 8 | 9 | public class MyEntityDaoDelegate implements DelegateQueryHandler, MyEntityDao { 10 | 11 | @Inject 12 | private QueryInvocationContext context; 13 | 14 | @Override 15 | public E saveAndFlushAndRefresh(E entity) { 16 | entityManager().persist(entity); 17 | entityManager().flush(); 18 | entityManager().refresh(entity); 19 | return entity; 20 | } 21 | 22 | private EntityManager entityManager() { 23 | return context.getEntityManager(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/QueryBuilderFactory.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | import javax.enterprise.inject.Any; 4 | import javax.enterprise.inject.Instance; 5 | import javax.inject.Inject; 6 | 7 | import com.ctp.cdi.query.QueryResult; 8 | import com.ctp.cdi.query.meta.DaoMethod; 9 | import com.ctp.cdi.query.meta.QueryInvocationLiteral; 10 | 11 | public class QueryBuilderFactory { 12 | 13 | @Inject @Any 14 | private Instance queryBuilder; 15 | 16 | public QueryBuilder build(DaoMethod method) { 17 | QueryBuilder builder = queryBuilder.select(new QueryInvocationLiteral(method.getMethodType())).get(); 18 | if (method.returns(QueryResult.class)) { 19 | return new WrappedQueryBuilder(builder); 20 | } 21 | return builder; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/LessThanOrEqual.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class LessThanOrEqual> extends SingleValueBuilder { 13 | 14 | public LessThanOrEqual(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.lessThanOrEqualTo(path.get(att), value)); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Tee2.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.Id; 6 | import javax.persistence.IdClass; 7 | 8 | /** 9 | * 10 | */ 11 | @IdClass(TeeId.class) 12 | @Entity 13 | public class Tee2 { 14 | @Column(nullable = false) 15 | @Id 16 | private long teeSetId; 17 | 18 | @Column(nullable = false) 19 | @Id 20 | private long holeId; 21 | 22 | public long getTeeSetId() { 23 | return teeSetId; 24 | } 25 | 26 | public void setTeeSetId(long teeSetId) { 27 | this.teeSetId = teeSetId; 28 | } 29 | 30 | public long getHoleId() { 31 | return holeId; 32 | } 33 | 34 | public void setHoleId(long holeId) { 35 | this.holeId = holeId; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/test/resources-glassfish/test-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.eclipse.persistence.jpa.PersistenceProvider 5 | jdbc/test 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/GreaterThanOrEqual.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class GreaterThanOrEqual> extends SingleValueBuilder { 13 | 14 | public GreaterThanOrEqual(SingularAttribute att, V value) { 15 | super(att, value); 16 | } 17 | 18 | @Override 19 | public List build(CriteriaBuilder builder, Path path) { 20 | return Arrays.asList(builder.greaterThanOrEqualTo(path.get(att), value)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Abs.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Abs extends SingularAttributeSelection { 12 | 13 | public Abs(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.abs(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Max.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Max extends SingularAttributeSelection { 12 | 13 | public Max(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.max(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Min.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Min extends SingularAttributeSelection { 12 | 13 | public Min(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.min(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Neg.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Neg extends SingularAttributeSelection { 12 | 13 | public Neg(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.neg(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Sum.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Sum extends SingularAttributeSelection { 12 | 13 | public Sum(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.sum(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/Statistics.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | public class Statistics { 4 | 5 | private final Double average; 6 | private final Long count; 7 | 8 | public Statistics(Double average, Long count) { 9 | this.average = average; 10 | this.count = count; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | StringBuilder builder = new StringBuilder(); 16 | builder.append("Statistics [") 17 | .append("average=").append(average) 18 | .append(", count=").append(count) 19 | .append("]"); 20 | return builder.toString(); 21 | } 22 | 23 | public Double getAverage() { 24 | return average; 25 | } 26 | 27 | public Long getCount() { 28 | return count; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/spi/QueryInvocationContext.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.spi; 2 | 3 | import javax.persistence.EntityManager; 4 | 5 | /** 6 | * Expose the current query invocation to extensions. 7 | */ 8 | public interface QueryInvocationContext { 9 | 10 | /** 11 | * Entity Manager used for the query. 12 | */ 13 | EntityManager getEntityManager(); 14 | 15 | /** 16 | * The class of the Entity related to the invoked DAO. 17 | */ 18 | Class getEntityClass(); 19 | 20 | /** 21 | * Given the object parameter is an entity, checks if the entity is 22 | * persisted or not. 23 | * @param entity Entity object, non nullable. 24 | * @return true if the entity is not persisted, false otherwise and if no entity. 25 | */ 26 | boolean isNew(Object entity); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/strings/Lower.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.strings; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Lower

extends SingularAttributeSelection { 12 | 13 | public Lower(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.lower(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/strings/Upper.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.strings; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Upper

extends SingularAttributeSelection { 12 | 13 | public Upper(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 19 | return builder.upper(path.get(attribute)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleDaoWithOverriddenEntityManager.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.EntityManager; 6 | 7 | import com.ctp.cdi.query.AbstractEntityDao; 8 | import com.ctp.cdi.query.test.domain.Simple; 9 | 10 | public abstract class SimpleDaoWithOverriddenEntityManager extends AbstractEntityDao { 11 | 12 | @Override @Simplistic 13 | protected abstract EntityManager entityManager(); 14 | 15 | public abstract List findByName(String name); 16 | 17 | public List findWithEm(String name) { 18 | return entityManager().createQuery("select s from Simple s where s.name = ?1", Simple.class) 19 | .setParameter(1, name) 20 | .getResultList(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /dist/src/main/assembly/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | CDI Query ${project.version} 3 | =================================== 4 | 5 | 6 | Contents of distribution 7 | ======================== 8 | 9 | artifacts/ 10 | 11 | Provided libraries 12 | 13 | doc/ 14 | 15 | API Docs and reference guide. 16 | 17 | lib/ 18 | 19 | CDI Query dependencies 20 | 21 | source/ 22 | 23 | Source code for this module 24 | 25 | Licensing 26 | ========= 27 | 28 | This distribution, as a whole, is licensed under the terms of the Apache 29 | Software License, Version 2.0 (ASL). 30 | 31 | URLs 32 | ================== 33 | 34 | Home Page: http://ctpconsulting.github.com/query/ 35 | Source Code: git://github.com/ctpconsulting/query.git 36 | Issue Tracking: https://github.com/ctpconsulting/query 37 | 38 | Release Notes 39 | ============= 40 | 41 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/Initialized.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.Target; 6 | 7 | import javax.inject.Qualifier; 8 | 9 | import static java.lang.annotation.ElementType.FIELD; 10 | import static java.lang.annotation.ElementType.METHOD; 11 | import static java.lang.annotation.ElementType.PARAMETER; 12 | import static java.lang.annotation.ElementType.TYPE; 13 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 14 | 15 | /** 16 | * CDI qualifier. Mainly used for producers which create an initialized instance. 17 | * 18 | * @author thomashug 19 | */ 20 | @Qualifier 21 | @Target({ TYPE, METHOD, PARAMETER, FIELD }) 22 | @Retention(RUNTIME) 23 | @Documented 24 | public @interface Initialized { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/AndQueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | import com.ctp.cdi.query.builder.QueryBuilderContext; 4 | import com.ctp.cdi.query.meta.DaoComponent; 5 | 6 | /** 7 | * 8 | * @author thomashug 9 | */ 10 | class AndQueryPart extends ConnectingQueryPart { 11 | 12 | public AndQueryPart(boolean first) { 13 | super(first); 14 | } 15 | 16 | @Override 17 | protected QueryPart build(String queryPart, String method, DaoComponent dao) { 18 | children.add(new PropertyQueryPart().build(queryPart, method, dao)); 19 | return this; 20 | } 21 | 22 | @Override 23 | protected QueryPart buildQuery(QueryBuilderContext ctx) { 24 | if (!first) { 25 | ctx.append(" and "); 26 | } 27 | buildQueryForChildren(ctx); 28 | return this; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/test-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.apache.openjpa.persistence.PersistenceProviderImpl 5 | testDatabase 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/Between.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | 12 | public class Between> extends SingleValueBuilder { 13 | 14 | private final V upper; 15 | 16 | public Between(SingularAttribute att, V lower, V upper) { 17 | super(att, lower); 18 | this.upper = upper; 19 | } 20 | 21 | @Override 22 | public List build(CriteriaBuilder builder, Path path) { 23 | return Arrays.asList(builder.between(path.get(att), value, upper)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Avg.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Avg extends SingularAttributeSelection { 12 | 13 | public Avg(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @SuppressWarnings("unchecked") 18 | @Override 19 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 20 | return (Selection) builder.avg(path.get(attribute)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/strings/SubstringFromTo.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.strings; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | public class SubstringFromTo

extends SubstringFrom

{ 10 | 11 | private final int length; 12 | 13 | public SubstringFromTo(SingularAttribute attribute, int from, int length) { 14 | super(attribute, from); 15 | this.length = length; 16 | } 17 | 18 | @Override 19 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 20 | return builder.substring(path.get(attribute), from, length); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Count.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Count extends SingularAttributeSelection { 12 | 13 | public Count(SingularAttribute attribute) { 14 | super(attribute); 15 | } 16 | 17 | @Override 18 | @SuppressWarnings("unchecked") 19 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 20 | return (Selection) builder.count(path.get(attribute)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /faces/src/main/java/com/ctp/cdi/query/home/FacesNavigationProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | import javax.faces.context.FacesContext; 4 | 5 | @FacesHome 6 | public class FacesNavigationProvider implements NavigationProvider { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | @Override 11 | public boolean isPostback() { 12 | return FacesContext.getCurrentInstance().isPostback(); 13 | } 14 | 15 | @Override 16 | public Object create() { 17 | return "create?faces-redirect=true"; 18 | } 19 | 20 | @Override 21 | public Object view(Object primaryKey) { 22 | return "view?faces-redirect=true&id=" + primaryKey; 23 | } 24 | 25 | @Override 26 | public Object exception() { 27 | return null; 28 | } 29 | 30 | @Override 31 | public Object search() { 32 | return "search?faces-redirect=true"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/SimpleBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.EntityManager; 4 | 5 | public class SimpleBuilder { 6 | 7 | private final EntityManager entityManager; 8 | 9 | public SimpleBuilder(EntityManager entityManager) { 10 | this.entityManager = entityManager; 11 | } 12 | 13 | public Simple createSimple(String name, Integer counter) { 14 | Simple result = new Simple(name); 15 | result.setCounter(counter); 16 | return persistSimple(result); 17 | } 18 | 19 | public Simple createSimple(String name) { 20 | Simple result = new Simple(name); 21 | return persistSimple(result); 22 | } 23 | 24 | public Simple persistSimple(Simple result) { 25 | entityManager.persist(result); 26 | entityManager.flush(); 27 | return result; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/QueryInvocation.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.METHOD; 5 | import static java.lang.annotation.ElementType.PARAMETER; 6 | import static java.lang.annotation.ElementType.TYPE; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | import java.lang.annotation.Documented; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.Target; 12 | 13 | import javax.inject.Qualifier; 14 | 15 | /** 16 | * CDI qualifier - defines the kind of query invocation. Mainly used 17 | * to resolve the correct query builder by method type. 18 | * 19 | * @author thomashug 20 | */ 21 | @Qualifier 22 | @Target({ TYPE, METHOD, PARAMETER, FIELD }) 23 | @Retention(RUNTIME) 24 | @Documented 25 | public @interface QueryInvocation { 26 | 27 | MethodType value(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/numeric/Modulo.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.numeric; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class Modulo

extends SingularAttributeSelection { 12 | 13 | private final Integer modulo; 14 | 15 | public Modulo(SingularAttribute attribute, Integer modulo) { 16 | super(attribute); 17 | this.modulo = modulo; 18 | } 19 | 20 | @Override 21 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 22 | return builder.mod(path.get(attribute), modulo); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/selection/strings/SubstringFrom.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.selection.strings; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.criteria.Selection; 7 | import javax.persistence.metamodel.SingularAttribute; 8 | 9 | import com.ctp.cdi.query.criteria.selection.SingularAttributeSelection; 10 | 11 | public class SubstringFrom

extends SingularAttributeSelection { 12 | 13 | final int from; 14 | 15 | public SubstringFrom(SingularAttribute attribute, int from) { 16 | super(attribute); 17 | this.from = from; 18 | } 19 | 20 | @Override 21 | public Selection toSelection(CriteriaQuery query, CriteriaBuilder builder, Path path) { 22 | return builder.substring(path.get(attribute), from); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/HomeEntityHome.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | import javax.persistence.metamodel.SingularAttribute; 7 | 8 | import com.ctp.cdi.query.EntityDao; 9 | import com.ctp.cdi.query.home.EntityHome; 10 | import com.ctp.cdi.query.test.domain.Home; 11 | import com.ctp.cdi.query.test.domain.Home_; 12 | 13 | public class HomeEntityHome extends EntityHome { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | @Inject 18 | private HomeDao dao; 19 | 20 | @Override 21 | public EntityDao getEntityDao() { 22 | return dao; 23 | } 24 | 25 | @Override 26 | protected List> searchAttributes() { 27 | return singularAttributes() 28 | .addIfNotEmpty(getSearch().getName(), Home_.name) 29 | .getAttributes(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /impl/src/test/resources-glassfish/test-mapped-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.eclipse.persistence.jpa.PersistenceProvider 5 | jdbc/test 6 | META-INF/orm.xml 7 | META-INF/custom-orm.xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/util/EntityUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.junit.Assert; 6 | 7 | import org.junit.Test; 8 | 9 | import com.ctp.cdi.query.test.domain.Tee; 10 | import com.ctp.cdi.query.test.domain.Tee2; 11 | import com.ctp.cdi.query.test.domain.TeeId; 12 | 13 | public class EntityUtilsTest { 14 | 15 | @Test 16 | public void should_find_id_property_class() { 17 | // given 18 | 19 | // when 20 | Class pkClass = EntityUtils.primaryKeyClass(Tee.class); 21 | 22 | // then 23 | Assert.assertEquals(TeeId.class, pkClass); 24 | } 25 | 26 | @Test 27 | public void should_find_id_class() { 28 | // given 29 | 30 | // when 31 | Class pkClass = EntityUtils.primaryKeyClass(Tee2.class); 32 | 33 | // then 34 | Assert.assertEquals(TeeId.class, pkClass); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/META-INF/orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | com.ctp.cdi.query.test.domain.mapped 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.apache.openjpa.persistence.PersistenceProviderImpl 5 | testDatabase 6 | META-INF/orm.xml 7 | META-INF/custom-orm.xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/test-mapped-persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.apache.openjpa.persistence.PersistenceProviderImpl 5 | testDatabase 6 | META-INF/orm.xml 7 | META-INF/custom-orm.xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/TransactionalTestCase.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test; 2 | 3 | import javax.annotation.Resource; 4 | import javax.persistence.EntityManager; 5 | import javax.transaction.UserTransaction; 6 | 7 | import org.jboss.arquillian.junit.Arquillian; 8 | import org.junit.After; 9 | import org.junit.Before; 10 | import org.junit.runner.RunWith; 11 | 12 | @RunWith(Arquillian.class) 13 | public abstract class TransactionalTestCase { 14 | 15 | @Resource 16 | protected UserTransaction ut; 17 | 18 | @Before 19 | public void startTransaction() throws Exception { 20 | // temp fix - OpenJPA seems not to properly initialize the static 21 | // metamodel otherwise. 22 | getEntityManager().getMetamodel(); 23 | ut.begin(); 24 | } 25 | 26 | @After 27 | public void rollbackTransaction() throws Exception { 28 | ut.rollback(); 29 | } 30 | 31 | protected abstract EntityManager getEntityManager(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /impl/src/test/resources/test-custom-orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.ctp.cdi.query.test.domain.mapped 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /impl/src/test/resources-openejb/META-INF/custom-orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.ctp.cdi.query.test.domain.mapped 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/MethodExpressionException.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | public class MethodExpressionException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | private final String property; 7 | private final Class daoClass; 8 | private final String method; 9 | 10 | public MethodExpressionException(Class daoClass, String method) { 11 | this(null, daoClass, method); 12 | } 13 | 14 | public MethodExpressionException(String property, Class daoClass, String method) { 15 | this.property = property; 16 | this.daoClass = daoClass; 17 | this.method = method; 18 | } 19 | 20 | @Override 21 | public String getMessage() { 22 | if (property != null) { 23 | return "Invalid property '" + property + "' in method expression " + daoClass.getName() + "." + method; 24 | } 25 | return "Method '" + method + "'of DAO " + daoClass.getName() + " is not a method expression"; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/meta/verifier/EntityVerifierTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.verifier; 2 | 3 | import static org.junit.Assert.assertFalse; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | import com.ctp.cdi.query.test.domain.Simple; 9 | 10 | public class EntityVerifierTest { 11 | 12 | @Test 13 | public void should_accept_entity_class() { 14 | // given 15 | EntityVerifier entityVerifier = new EntityVerifier(); 16 | 17 | // when 18 | boolean isValid = entityVerifier.verify(Simple.class); 19 | 20 | // then 21 | assertTrue(isValid); 22 | } 23 | 24 | @Test 25 | public void should_not_accept_class_without_entity_annotation() { 26 | // given 27 | EntityVerifier entityVerifier = new EntityVerifier(); 28 | 29 | // when 30 | boolean isValid = entityVerifier.verify(EntityWithoutId.class); 31 | 32 | // then 33 | assertFalse(isValid); 34 | 35 | } 36 | 37 | private static class EntityWithoutId { 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/extractor/AnnotationMetadataExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.extractor; 2 | 3 | import com.ctp.cdi.query.Dao; 4 | import com.ctp.cdi.query.NonEntity; 5 | import com.ctp.cdi.query.meta.DaoEntity; 6 | import com.ctp.cdi.query.meta.verifier.EntityVerifier; 7 | import com.ctp.cdi.query.meta.verifier.Verifier; 8 | import com.ctp.cdi.query.util.EntityUtils; 9 | 10 | public class AnnotationMetadataExtractor implements MetadataExtractor { 11 | 12 | private final Verifier> verifier; 13 | 14 | public AnnotationMetadataExtractor() { 15 | this.verifier = new EntityVerifier(); 16 | } 17 | 18 | @Override 19 | public DaoEntity extract(Class daoClass) { 20 | Dao dao = daoClass.getAnnotation(Dao.class); 21 | Class daoEntity = dao.value(); 22 | boolean isEntityClass = !NonEntity.class.equals(daoEntity) && verifier.verify(daoEntity); 23 | if (isEntityClass) { 24 | return new DaoEntity(daoEntity, EntityUtils.primaryKeyClass(daoEntity)); 25 | } 26 | return null; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Principal.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Principal { 9 | 10 | @Id @GeneratedValue 11 | private Long id; 12 | 13 | private String name; 14 | 15 | public Principal() { 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | StringBuilder builder = new StringBuilder(); 21 | builder.append("Principal [id=").append(id) 22 | .append(", name=").append(name).append("]"); 23 | return builder.toString(); 24 | } 25 | 26 | public Principal(String name) { 27 | this.name = name; 28 | } 29 | 30 | public Long getId() { 31 | return id; 32 | } 33 | 34 | public void setId(Long id) { 35 | this.id = id; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/OrBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import javax.persistence.criteria.CriteriaBuilder; 8 | import javax.persistence.criteria.Path; 9 | import javax.persistence.criteria.Predicate; 10 | 11 | import com.ctp.cdi.query.criteria.Criteria; 12 | 13 | public class OrBuilder

implements PredicateBuilder

{ 14 | 15 | final Criteria[] criteria; 16 | 17 | public OrBuilder(Criteria... criteria) { 18 | this.criteria = criteria; 19 | } 20 | 21 | @Override 22 | public List build(CriteriaBuilder builder, Path

path) { 23 | List and = new ArrayList(criteria.length); 24 | for (Criteria c : criteria) { 25 | and.add(builder.and( 26 | c.predicates(builder, path).toArray(new Predicate[0]))); 27 | } 28 | return Arrays.asList(builder.or(and.toArray(new Predicate[0]))); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/processor/OrderBy.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.processor; 2 | 3 | import javax.persistence.criteria.CriteriaBuilder; 4 | import javax.persistence.criteria.CriteriaQuery; 5 | import javax.persistence.criteria.Path; 6 | import javax.persistence.metamodel.SingularAttribute; 7 | 8 | import com.ctp.cdi.query.builder.OrderDirection; 9 | 10 | 11 | public class OrderBy implements QueryProcessor

{ 12 | 13 | private final SingularAttribute att; 14 | private final OrderDirection dir; 15 | 16 | public OrderBy(SingularAttribute att, OrderDirection dir) { 17 | this.att = att; 18 | this.dir = dir; 19 | } 20 | 21 | @Override 22 | public void process(CriteriaQuery query, CriteriaBuilder builder, Path

path) { 23 | switch (dir) { 24 | case ASC: 25 | query.orderBy(builder.asc(path.get(att))); 26 | break; 27 | default: 28 | query.orderBy(builder.desc(path.get(att))); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /impl/src/test/resources-glassfish/arquillian.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | target/arquillian 12 | 13 | 14 | 15 | 16 | target/glassfish3 17 | true 18 | true 19 | src/test/resources-glassfish/glassfish-resources.xml 20 | src/test/resources-glassfish/glassfish-resources.xml 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/In.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.Path; 8 | import javax.persistence.criteria.Predicate; 9 | import javax.persistence.metamodel.SingularAttribute; 10 | 11 | public class In implements PredicateBuilder

{ 12 | 13 | SingularAttribute singular; 14 | V[] values; 15 | 16 | public In(SingularAttribute singular, V[] values) { 17 | this.singular = singular; 18 | this.values = Arrays.copyOf(values, values.length); 19 | } 20 | 21 | @Override 22 | public List build(CriteriaBuilder builder, Path

path) { 23 | Path p = path.get(singular); 24 | CriteriaBuilder.In in = builder.in(p); 25 | for (V value : values) { 26 | if (value != null) { 27 | in.value(value); 28 | } 29 | } 30 | return Arrays.asList((Predicate) in); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/OrQueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | import static com.ctp.cdi.query.util.QueryUtils.splitByKeyword; 4 | 5 | import com.ctp.cdi.query.builder.QueryBuilderContext; 6 | import com.ctp.cdi.query.meta.DaoComponent; 7 | 8 | /** 9 | * @author thomashug 10 | */ 11 | class OrQueryPart extends ConnectingQueryPart { 12 | 13 | public OrQueryPart(boolean first) { 14 | super(first); 15 | } 16 | 17 | @Override 18 | protected QueryPart build(String queryPart, String method, DaoComponent dao) { 19 | String[] andParts = splitByKeyword(queryPart, "And"); 20 | boolean first = true; 21 | for (String and : andParts) { 22 | AndQueryPart andPart = new AndQueryPart(first); 23 | first = false; 24 | children.add(andPart.build(and, method, dao)); 25 | } 26 | return this; 27 | } 28 | 29 | @Override 30 | protected QueryPart buildQuery(QueryBuilderContext ctx) { 31 | if (!first) { 32 | ctx.append(" or "); 33 | } 34 | buildQueryForChildren(ctx); 35 | return this; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /docs/src/main/docbook/en-US/master.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/QueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import com.ctp.cdi.query.builder.QueryBuilderContext; 8 | import com.ctp.cdi.query.meta.DaoComponent; 9 | 10 | /** 11 | * 12 | * @author thomashug 13 | */ 14 | public abstract class QueryPart { 15 | 16 | protected List children = new LinkedList(); 17 | 18 | protected abstract QueryPart build(String queryPart, String method, DaoComponent dao); 19 | 20 | protected abstract QueryPart buildQuery(QueryBuilderContext ctx); 21 | 22 | protected void buildQueryForChildren(QueryBuilderContext ctx) { 23 | for (QueryPart child : children) { 24 | child.buildQuery(ctx); 25 | } 26 | } 27 | 28 | protected boolean hasChildren(Set> excluded) { 29 | if (children == null || children.isEmpty()) { 30 | return false; 31 | } 32 | for (QueryPart part : children) { 33 | if (!excluded.contains(part.getClass())) { 34 | return true; 35 | } 36 | } 37 | return false; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/PersistenceUnit.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import java.util.List; 4 | 5 | class PersistenceUnit { 6 | 7 | public static final String RESOURCE_PATH = "META-INF/persistence.xml"; 8 | public static final String DEFAULT_ORM_PATH = "META-INF/orm.xml"; 9 | 10 | private final String unitName; 11 | private final List entities; 12 | 13 | PersistenceUnit(String unitName, List entities) { 14 | this.unitName = unitName; 15 | this.entities = entities; 16 | } 17 | 18 | public EntityDescriptor find(Class entityClass) { 19 | for (EntityDescriptor entity : entities) { 20 | if (entity.is(entityClass)) { 21 | return entity; 22 | } 23 | } 24 | return null; 25 | } 26 | 27 | public String getUnitName() { 28 | return unitName; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | StringBuilder builder = new StringBuilder(); 34 | builder.append("PersistenceUnit [unitName=").append(unitName) 35 | .append(", entities=").append(entities).append("]"); 36 | return builder.toString(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/MethodQueryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | import javax.persistence.Query; 4 | 5 | import com.ctp.cdi.query.builder.part.QueryRoot; 6 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 7 | import com.ctp.cdi.query.meta.MethodType; 8 | import com.ctp.cdi.query.meta.QueryInvocation; 9 | import com.ctp.cdi.query.param.Parameters; 10 | 11 | /** 12 | * 13 | * @author thomashug 14 | */ 15 | @QueryInvocation(MethodType.PARSE) 16 | public class MethodQueryBuilder extends QueryBuilder { 17 | 18 | @Override 19 | public Object execute(CdiQueryInvocationContext context) { 20 | Query jpaQuery = createJpaQuery(context); 21 | return context.executeQuery(jpaQuery); 22 | } 23 | 24 | private Query createJpaQuery(CdiQueryInvocationContext context) { 25 | Parameters params = context.getParams(); 26 | QueryRoot root = context.getDaoMethod().getQueryRoot(); 27 | String jpqlQuery = context.applyQueryStringPostProcessors(root.getJpqlQuery()); 28 | context.setQueryString(jpqlQuery); 29 | Query result = params.applyTo(context.getEntityManager().createQuery(jpqlQuery)); 30 | return applyRestrictions(context, result); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /docs/src/main/xslt/common.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/jpa/QueryStringExtractorFactory.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util.jpa; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import javax.persistence.Query; 7 | 8 | public class QueryStringExtractorFactory { 9 | 10 | private final List extractors = Arrays.asList( 11 | new HibernateQueryStringExtractor(), 12 | new EclipseLinkEjbQueryStringExtractor(), 13 | new OpenJpaQueryStringExtractor()); 14 | 15 | public QueryStringExtractor select(Query query) { 16 | for (QueryStringExtractor extractor : extractors) { 17 | String compare = extractor.getClass().getAnnotation(ProviderSpecific.class).value(); 18 | if (isQueryClass(compare, query)) { 19 | return extractor; 20 | } 21 | } 22 | throw new RuntimeException("Persistence provider not supported"); 23 | } 24 | 25 | private boolean isQueryClass(String clazzName, Query query) { 26 | try { 27 | Class toClass = Class.forName(clazzName); 28 | toClass.cast(query); 29 | return true; 30 | } catch (Exception e) { 31 | return false; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/DaoEntity.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Data structure to store information about an entity: 7 | *

    8 | *
  • Stores the class of the entity
  • 9 | *
  • Stores the primary key class
  • 10 | *
11 | * 12 | * @author thomashug 13 | */ 14 | public class DaoEntity { 15 | 16 | private Class entityClass; 17 | private Class primaryClass; 18 | 19 | public DaoEntity(Class entityClass) { 20 | this(entityClass, null); 21 | } 22 | 23 | public DaoEntity(Class entityClass, Class primaryClass) { 24 | this.entityClass = entityClass; 25 | this.primaryClass = primaryClass; 26 | } 27 | 28 | public Class getEntityClass() { 29 | return entityClass; 30 | } 31 | 32 | public void setEntityClass(Class entityClass) { 33 | this.entityClass = entityClass; 34 | } 35 | 36 | public Class getPrimaryClass() { 37 | return primaryClass; 38 | } 39 | 40 | public void setPrimaryClass(Class primaryClass) { 41 | this.primaryClass = primaryClass; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/AbstractEntityDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.EntityManager; 6 | import javax.persistence.criteria.CriteriaQuery; 7 | 8 | 9 | /** 10 | * Base DAO class to be extended by concrete implementations. 11 | * @author thomashug 12 | * 13 | * @param Entity type. 14 | * @param Primary key type. 15 | */ 16 | @Dao 17 | public abstract class AbstractEntityDao 18 | implements EntityDao { 19 | 20 | /** 21 | * Utility method to get hold of the entity manager for this DAO. 22 | * This method can be overridden and decorated with qualifiers. If done, the qualifiers 23 | * will be used to resolve a specific entity manager other than the default one. 24 | * 25 | * @return Entity manager instance. 26 | */ 27 | protected abstract EntityManager entityManager(); 28 | 29 | /** 30 | * Utility method to create a criteria query. 31 | * @return Criteria query 32 | */ 33 | protected abstract CriteriaQuery criteriaQuery(); 34 | 35 | /** 36 | * Get the entity class this DAO is related to. 37 | * @return DAO entity class. 38 | */ 39 | protected abstract Class entityClass(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/meta/extractor/TypeMetadataExtractorTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.extractor; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertNull; 6 | 7 | import org.junit.Test; 8 | 9 | import com.ctp.cdi.query.meta.DaoEntity; 10 | import com.ctp.cdi.query.test.domain.Simple; 11 | import com.ctp.cdi.query.test.service.DaoInterface; 12 | import com.ctp.cdi.query.test.service.SimpleDao; 13 | 14 | public class TypeMetadataExtractorTest { 15 | 16 | @Test 17 | public void should_extract_from_class() { 18 | // given 19 | MetadataExtractor extractor = new TypeMetadataExtractor(); 20 | 21 | // when 22 | DaoEntity result = extractor.extract(SimpleDao.class); 23 | 24 | // then 25 | assertNotNull(result); 26 | assertEquals(Simple.class, result.getEntityClass()); 27 | assertEquals(Long.class, result.getPrimaryClass()); 28 | } 29 | 30 | @Test 31 | public void should_not_extract_from_annotation() { 32 | // given 33 | MetadataExtractor extractor = new TypeMetadataExtractor(); 34 | 35 | // when 36 | DaoEntity result = extractor.extract(DaoInterface.class); 37 | 38 | // then 39 | assertNull(result); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/QueryOperator.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | /** 4 | * Comparison options for queries. 5 | * @author thomashug 6 | */ 7 | public enum QueryOperator { 8 | 9 | LessThan("LessThan", "{0} < {1}"), 10 | LessThanEquals("LessThanEquals", "{0} <= {1}"), 11 | GreaterThan("GreaterThan", "{0} > {1}"), 12 | GreaterThanEquals("GreaterThanEquals", "{0} >= {1}"), 13 | Like("Like", "{0} like {1}"), 14 | NotEqual("NotEqual", "{0} <> {1}"), 15 | Equal("Equal", "{0} = {1}"), 16 | Between("Between", "{0} between {1} and {2}", 2), 17 | IsNotNull("IsNotNull", "{0} IS NOT NULL", 0), 18 | IsNull("IsNull", "{0} IS NULL", 0); 19 | 20 | private final String expression; 21 | private final String jpql; 22 | private final int paramNum; 23 | 24 | private QueryOperator(String expression, String jpql) { 25 | this(expression, jpql, 1); 26 | } 27 | 28 | private QueryOperator(String expression, String jpql, int paramNum) { 29 | this.expression = expression; 30 | this.jpql = jpql; 31 | this.paramNum = paramNum; 32 | } 33 | 34 | public String getExpression() { 35 | return expression; 36 | } 37 | 38 | public String getJpql() { 39 | return jpql; 40 | } 41 | 42 | public int getParamNum() { 43 | return paramNum; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /impl/src/test/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/Parent.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | import javax.persistence.CascadeType; 7 | import javax.persistence.Entity; 8 | 9 | @Entity 10 | public class Parent extends NamedEntity { 11 | 12 | @javax.persistence.OneToOne(cascade = CascadeType.ALL) 13 | private OneToOne one; 14 | 15 | @javax.persistence.OneToMany(cascade = CascadeType.ALL) 16 | private List many = new LinkedList(); 17 | 18 | private Long value = Long.valueOf(0); 19 | 20 | public Parent() { 21 | super(); 22 | } 23 | 24 | public Parent(String name) { 25 | super(name); 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Parent [value=" + value + ", getName()=" + getName() + ", getId()=" + getId() + "]"; 31 | } 32 | 33 | public void add(OneToMany otm) { 34 | many.add(otm); 35 | } 36 | 37 | public OneToOne getOne() { 38 | return one; 39 | } 40 | 41 | public void setOne(OneToOne one) { 42 | this.one = one; 43 | } 44 | 45 | public List getMany() { 46 | return many; 47 | } 48 | 49 | public Long getValue() { 50 | return value; 51 | } 52 | 53 | public void setValue(Long value) { 54 | this.value = value; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/AuditEntityListener.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import java.util.Set; 4 | 5 | import javax.enterprise.inject.spi.Bean; 6 | import javax.enterprise.inject.spi.BeanManager; 7 | import javax.persistence.PrePersist; 8 | import javax.persistence.PreUpdate; 9 | 10 | import org.jboss.solder.beanManager.BeanManagerLocator; 11 | 12 | public class AuditEntityListener { 13 | 14 | @PrePersist 15 | public void persist(Object entity) { 16 | BeanManager beanManager = new BeanManagerLocator().getBeanManager(); 17 | Set> beans = beanManager.getBeans(PrePersistAuditListener.class); 18 | for (Bean bean : beans) { 19 | PrePersistAuditListener result = (PrePersistAuditListener) beanManager.getReference( 20 | bean, PrePersistAuditListener.class, beanManager.createCreationalContext(bean)); 21 | result.prePersist(entity); 22 | } 23 | } 24 | 25 | @PreUpdate 26 | public void update(Object entity) { 27 | BeanManager beanManager = new BeanManagerLocator().getBeanManager(); 28 | Set> beans = beanManager.getBeans(PreUpdateAuditListener.class); 29 | for (Bean bean : beans) { 30 | PreUpdateAuditListener result = (PreUpdateAuditListener) beanManager.getReference( 31 | bean, PreUpdateAuditListener.class, beanManager.createCreationalContext(bean)); 32 | result.preUpdate(entity); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/MappedSuperclassDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import static com.ctp.cdi.query.util.QueryUtils.isEmpty; 4 | 5 | import java.io.Serializable; 6 | 7 | 8 | class MappedSuperclassDescriptor extends PersistentClassDescriptor { 9 | 10 | MappedSuperclassDescriptor(String name, String packageName, String className, String idClass, String id) { 11 | super(name, packageName, className, idClass, id); 12 | } 13 | 14 | @Override 15 | public Class getIdClass() { 16 | if (idClass == null && getParent() != null) { 17 | return getParent().getIdClass(); 18 | } 19 | return super.getIdClass(); 20 | } 21 | 22 | @Override 23 | public String getId() { 24 | if (isEmpty(id) && getParent() != null) { 25 | return getParent().getId(); 26 | } 27 | return super.getId(); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | StringBuilder builder = new StringBuilder(); 33 | builder.append("MappedSuperclassDescriptor ") 34 | .append("[entityClass=").append(className(entityClass)) 35 | .append(", name=").append(name) 36 | .append(", idClass=").append(className(idClass)) 37 | .append(", id=").append(id) 38 | .append(", parent=").append(getParent()) 39 | .append("]"); 40 | return builder.toString(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/BasePropertyQueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | import org.jboss.solder.properties.Property; 4 | import org.jboss.solder.properties.query.NamedPropertyCriteria; 5 | import org.jboss.solder.properties.query.PropertyQueries; 6 | import org.jboss.solder.properties.query.PropertyQuery; 7 | 8 | import com.ctp.cdi.query.builder.MethodExpressionException; 9 | import com.ctp.cdi.query.meta.DaoComponent; 10 | 11 | 12 | abstract class BasePropertyQueryPart extends QueryPart { 13 | 14 | final static String SEPARATOR = "_"; 15 | 16 | void validate(String name, String method, DaoComponent dao) { 17 | Class current = dao.getEntityClass(); 18 | if (name == null) { 19 | throw new MethodExpressionException(null, dao.getDaoClass(), method); 20 | } 21 | for (String property : name.split(SEPARATOR)) { 22 | PropertyQuery query = PropertyQueries.createQuery(current) 23 | .addCriteria(new NamedPropertyCriteria(property)); 24 | Property result = query.getFirstResult(); 25 | if (result == null) { 26 | throw new MethodExpressionException(property, dao.getDaoClass(), method); 27 | } 28 | current = result.getJavaClass(); 29 | } 30 | } 31 | 32 | String rewriteSeparator(String name) { 33 | if (name.contains("_")) { 34 | return name.replaceAll(SEPARATOR, "."); 35 | } 36 | return name; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/QueryExtensionTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | 5 | import javax.enterprise.inject.Instance; 6 | import javax.inject.Inject; 7 | 8 | import org.jboss.arquillian.container.test.api.Deployment; 9 | import org.jboss.arquillian.junit.Arquillian; 10 | import org.jboss.shrinkwrap.api.Archive; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | 14 | import com.ctp.cdi.query.test.domain.Simple; 15 | import com.ctp.cdi.query.test.service.DaoInterface; 16 | import com.ctp.cdi.query.test.service.ExtendedDaoInterface; 17 | import com.ctp.cdi.query.test.service.SimpleDao; 18 | import com.ctp.cdi.query.test.util.TestDeployments; 19 | 20 | @RunWith(Arquillian.class) 21 | public class QueryExtensionTest { 22 | 23 | @Deployment(order = 2) 24 | public static Archive deployment() { 25 | return TestDeployments.initDeployment() 26 | .addPackage(DaoInterface.class.getPackage()) 27 | .addPackages(true, Simple.class.getPackage()); 28 | } 29 | 30 | @Inject 31 | Instance dao; 32 | 33 | @Inject 34 | Instance extendedDao; 35 | 36 | @Inject 37 | Instance extendedClassDao; 38 | 39 | @Test 40 | public void should_inject() { 41 | assertNotNull(dao.get()); 42 | assertNotNull(extendedDao.get()); 43 | assertNotNull(extendedClassDao.get()); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/EntityDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import static com.ctp.cdi.query.util.QueryUtils.isEmpty; 4 | 5 | import java.io.Serializable; 6 | 7 | 8 | class EntityDescriptor extends PersistentClassDescriptor { 9 | 10 | EntityDescriptor(String name, String packageName, String className, String idClass, String id) { 11 | super(name, packageName, className, idClass, id); 12 | } 13 | 14 | public boolean is(Class entityClass) { 15 | return this.entityClass.equals(entityClass); 16 | } 17 | 18 | @Override 19 | public Class getIdClass() { 20 | if (idClass == null && getParent() != null) { 21 | return getParent().getIdClass(); 22 | } 23 | return super.getIdClass(); 24 | } 25 | 26 | @Override 27 | public String getId() { 28 | if (isEmpty(id) && getParent() != null) { 29 | return getParent().getId(); 30 | } 31 | return super.getId(); 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | StringBuilder builder = new StringBuilder(); 37 | builder.append("EntityDescriptor ") 38 | .append("[entityClass=").append(className(entityClass)) 39 | .append(", name=").append(name) 40 | .append(", idClass=").append(className(idClass)) 41 | .append(", id=").append(id) 42 | .append(", superClass=").append(getParent()) 43 | .append("]"); 44 | return builder.toString(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/handler/EntityManagerDaoHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import javax.enterprise.inject.Produces; 6 | import javax.inject.Inject; 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.PersistenceContext; 9 | 10 | import org.jboss.arquillian.container.test.api.Deployment; 11 | import org.jboss.shrinkwrap.api.Archive; 12 | import org.junit.Test; 13 | 14 | import com.ctp.cdi.query.test.TransactionalTestCase; 15 | import com.ctp.cdi.query.test.domain.Simple3; 16 | import com.ctp.cdi.query.test.service.SimpleEntityManagerDao; 17 | import com.ctp.cdi.query.test.util.TestDeployments; 18 | 19 | public class EntityManagerDaoHandlerTest extends TransactionalTestCase { 20 | 21 | @Deployment 22 | public static Archive deployment() { 23 | return TestDeployments.initDeployment() 24 | .addClasses(SimpleEntityManagerDao.class) 25 | .addPackage(Simple3.class.getPackage()); 26 | } 27 | 28 | @Produces 29 | @PersistenceContext 30 | private EntityManager entityManager; 31 | 32 | @Inject 33 | private SimpleEntityManagerDao dao; 34 | 35 | @Test 36 | public void should_persist_new_entity() { 37 | // given 38 | Simple3 simple = new Simple3(); 39 | 40 | // when 41 | dao.persist(simple); 42 | 43 | // then 44 | assertTrue(simple.getId() > 0); 45 | } 46 | 47 | @Override 48 | protected EntityManager getEntityManager() { 49 | return entityManager; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/criteria/QueryDslTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | 5 | import javax.enterprise.inject.Produces; 6 | import javax.inject.Inject; 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.PersistenceContext; 9 | 10 | import org.jboss.arquillian.container.test.api.Deployment; 11 | import org.jboss.shrinkwrap.api.Archive; 12 | import org.junit.Test; 13 | 14 | import com.ctp.cdi.query.test.TransactionalTestCase; 15 | import com.ctp.cdi.query.test.domain.Simple; 16 | import com.ctp.cdi.query.test.service.SimpleDao; 17 | import com.ctp.cdi.query.test.service.SimpleQueryDslDao; 18 | import com.ctp.cdi.query.test.util.TestDeployments; 19 | import com.mysema.query.jpa.impl.JPAQuery; 20 | 21 | public class QueryDslTest extends TransactionalTestCase { 22 | 23 | @Deployment 24 | public static Archive deployment() { 25 | return TestDeployments.initDeployment() 26 | .addPackage(SimpleDao.class.getPackage()) 27 | .addPackage(Simple.class.getPackage()); 28 | } 29 | 30 | @Produces 31 | @PersistenceContext 32 | private EntityManager entityManager; 33 | 34 | @Inject 35 | private SimpleQueryDslDao dao; 36 | 37 | @Override 38 | protected EntityManager getEntityManager() { 39 | return entityManager; 40 | } 41 | 42 | @Test 43 | public void should_instantiate_dsl_query() { 44 | // when 45 | JPAQuery query = dao.jpaQuery(); 46 | 47 | // then 48 | assertNotNull(query); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/spi/CdiQuerySpiTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.spi; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | 5 | import javax.enterprise.inject.Produces; 6 | import javax.inject.Inject; 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.PersistenceContext; 9 | 10 | import org.jboss.arquillian.container.test.api.Deployment; 11 | import org.jboss.shrinkwrap.api.Archive; 12 | import org.junit.Test; 13 | 14 | import com.ctp.cdi.query.test.TransactionalTestCase; 15 | import com.ctp.cdi.query.test.domain.Simple; 16 | import com.ctp.cdi.query.test.service.MySimpleDao; 17 | import com.ctp.cdi.query.test.service.SimpleDao; 18 | import com.ctp.cdi.query.test.util.TestDeployments; 19 | 20 | public class CdiQuerySpiTest extends TransactionalTestCase { 21 | 22 | @Deployment 23 | public static Archive deployment() { 24 | return TestDeployments.initDeployment() 25 | .addPackage(SimpleDao.class.getPackage()) 26 | .addPackage(Simple.class.getPackage()); 27 | } 28 | 29 | @Produces 30 | @PersistenceContext 31 | private EntityManager entityManager; 32 | 33 | @Inject 34 | private MySimpleDao dao; 35 | 36 | @Test 37 | public void should_call_delegate() { 38 | // given 39 | Simple simple = new Simple("test_call_delegate"); 40 | 41 | // when 42 | simple = dao.saveAndFlushAndRefresh(simple); 43 | 44 | // then 45 | assertNotNull(simple.getId()); 46 | } 47 | 48 | @Override 49 | protected EntityManager getEntityManager() { 50 | return entityManager; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/Query.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import javax.persistence.LockModeType; 9 | import javax.persistence.QueryHint; 10 | 11 | /** 12 | * Supply query meta data to a method with this annotation.
13 | * Currently supports: 14 | *
  • JPQL queries as part of the annotation value
  • 15 | *
  • Execute named queries referenced by the named value
  • 16 | *
  • Execute native SQL queries
  • 17 | *
  • Restrict the result size to a static value
  • 18 | *
  • Provide a lock mode
19 | * @author thomashug 20 | */ 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.METHOD) 23 | public @interface Query { 24 | 25 | /** 26 | * Defines the Query to execute. Can be left empty for method expression queries 27 | * or when referencing a {@link #named()} query. 28 | */ 29 | String value() default ""; 30 | 31 | /** 32 | * References a named query. 33 | */ 34 | String named() default ""; 35 | 36 | /** 37 | * Defines a native SQL query. 38 | */ 39 | String sql() default ""; 40 | 41 | /** 42 | * Limits the number of results the query returns. 43 | */ 44 | int max() default 0; 45 | 46 | /** 47 | * Defines a lock mode for the query. 48 | */ 49 | LockModeType lock() default LockModeType.NONE; 50 | 51 | /** 52 | * (Optional) Query properties and hints. May include vendor-specific query hints. 53 | */ 54 | QueryHint[] hints() default {}; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/part/PropertyQueryPart.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.part; 2 | 3 | import static com.ctp.cdi.query.util.QueryUtils.uncapitalize; 4 | 5 | import java.text.MessageFormat; 6 | 7 | import com.ctp.cdi.query.builder.QueryBuilder; 8 | import com.ctp.cdi.query.builder.QueryBuilderContext; 9 | import com.ctp.cdi.query.builder.QueryOperator; 10 | import com.ctp.cdi.query.meta.DaoComponent; 11 | 12 | /** 13 | * 14 | * @author thomashug 15 | */ 16 | class PropertyQueryPart extends BasePropertyQueryPart { 17 | 18 | private String name; 19 | private QueryOperator comparator; 20 | 21 | @Override 22 | protected QueryPart build(String queryPart, String method, DaoComponent dao) { 23 | comparator = QueryOperator.Equal; 24 | name = uncapitalize(queryPart); 25 | for (QueryOperator comp : QueryOperator.values()) { 26 | if (queryPart.endsWith(comp.getExpression())) { 27 | comparator = comp; 28 | name = uncapitalize(queryPart.substring(0, queryPart.indexOf(comp.getExpression()))); 29 | break; 30 | } 31 | } 32 | validate(name, method, dao); 33 | name = rewriteSeparator(name); 34 | return this; 35 | } 36 | 37 | @Override 38 | protected QueryPart buildQuery(QueryBuilderContext ctx) { 39 | String[] args = new String[comparator.getParamNum() + 1]; 40 | args[0] = QueryBuilder.ENTITY_NAME + "." + name; 41 | for (int i = 1; i < args.length; i++) { 42 | args[i] = "?" + ctx.increment(); 43 | } 44 | ctx.append(MessageFormat.format(comparator.getJpql(), (Object[]) args)); 45 | return this; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/TeeId.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Embeddable; 7 | 8 | @Embeddable 9 | @SuppressWarnings("serial") 10 | public class TeeId implements Serializable { 11 | 12 | @Column(nullable = false) 13 | private long teeSetId; 14 | 15 | @Column(nullable = false) 16 | private long holeId; 17 | 18 | public TeeId() { 19 | } 20 | 21 | public TeeId(long teeSetId, long holeId) { 22 | this.teeSetId = teeSetId; 23 | this.holeId = holeId; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | final int prime = 31; 29 | int result = 1; 30 | result = prime * result + (int) (holeId ^ (holeId >>> 32)); 31 | result = prime * result + (int) (teeSetId ^ (teeSetId >>> 32)); 32 | return result; 33 | } 34 | 35 | @Override 36 | public boolean equals(Object obj) { 37 | if (this == obj) 38 | return true; 39 | if (obj == null) 40 | return false; 41 | if (getClass() != obj.getClass()) 42 | return false; 43 | TeeId other = (TeeId) obj; 44 | if (holeId != other.holeId) 45 | return false; 46 | if (teeSetId != other.teeSetId) 47 | return false; 48 | return true; 49 | } 50 | 51 | public long getTeeSetId() { 52 | return teeSetId; 53 | } 54 | 55 | public void setTeeSetId(long teeSetId) { 56 | this.teeSetId = teeSetId; 57 | } 58 | 59 | public long getHoleId() { 60 | return holeId; 61 | } 62 | 63 | public void setHoleId(long holeId) { 64 | this.holeId = holeId; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/handler/QueryInvocationException.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import javax.interceptor.InvocationContext; 4 | 5 | public class QueryInvocationException extends RuntimeException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | public QueryInvocationException(Throwable t, CdiQueryInvocationContext context) { 10 | super(createMessage(context, t), t); 11 | } 12 | 13 | public QueryInvocationException(Throwable t, InvocationContext context) { 14 | super(createMessage(context, t), t); 15 | } 16 | 17 | private static final String createMessage(CdiQueryInvocationContext context, Throwable t) { 18 | StringBuilder builder = new StringBuilder(); 19 | builder.append("Exception calling DAO: ["); 20 | builder.append("DAO=").append(context.getDaoMethod().getDao().getDaoClass().getName()).append(","); 21 | builder.append("entity=").append(context.getEntityClass().getName()).append(","); 22 | builder.append("method=").append(context.getMethod().getName()).append(","); 23 | builder.append("query=").append(context.getQueryString()).append("],"); 24 | builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage()); 25 | return builder.toString(); 26 | } 27 | 28 | private static String createMessage(InvocationContext context, Throwable t) { 29 | StringBuilder builder = new StringBuilder(); 30 | builder.append("Exception calling DAO: ["); 31 | builder.append("DAO=").append(context.getTarget().getClass()).append(","); 32 | builder.append("method=").append(context.getMethod().getName()).append("],"); 33 | builder.append("exception=").append(t.getClass()).append(",message=").append(t.getMessage()); 34 | return builder.toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/postprocessor/OrderByQueryStringPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.postprocessor; 2 | 3 | import javax.persistence.metamodel.SingularAttribute; 4 | 5 | import com.ctp.cdi.query.builder.OrderDirection; 6 | import com.ctp.cdi.query.builder.QueryBuilder; 7 | import com.ctp.cdi.query.handler.QueryStringPostProcessor; 8 | 9 | public class OrderByQueryStringPostProcessor implements QueryStringPostProcessor { 10 | 11 | private static final String ORDER_BY = " order by "; 12 | 13 | private final String attribute; 14 | private OrderDirection direction; 15 | 16 | public OrderByQueryStringPostProcessor(SingularAttribute attribute, OrderDirection direction) { 17 | this.attribute = attribute.getName(); 18 | this.direction = direction; 19 | } 20 | 21 | public OrderByQueryStringPostProcessor(String attribute, OrderDirection direction) { 22 | this.attribute = attribute; 23 | this.direction = direction; 24 | } 25 | 26 | @Override 27 | public String postProcess(String queryString) { 28 | StringBuilder builder = new StringBuilder(queryString); 29 | if (queryString.contains(ORDER_BY)) { 30 | builder.append(","); 31 | } else { 32 | builder.append(ORDER_BY); 33 | } 34 | return builder.append(QueryBuilder.ENTITY_NAME).append(".").append(attribute) 35 | .append(" ").append(direction) 36 | .toString(); 37 | } 38 | 39 | public boolean matches(SingularAttribute attribute) { 40 | return matches(attribute.getName()); 41 | } 42 | 43 | public boolean matches(String attribute) { 44 | return this.attribute.equals(attribute); 45 | } 46 | 47 | public void changeDirection() { 48 | direction = direction.change(); 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/meta/extractor/AnnotationMetadataExtractorTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.extractor; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.Assert.assertNull; 6 | 7 | import org.junit.Test; 8 | 9 | import com.ctp.cdi.query.Dao; 10 | import com.ctp.cdi.query.meta.DaoEntity; 11 | import com.ctp.cdi.query.test.domain.Simple; 12 | import com.ctp.cdi.query.test.service.DaoInterface; 13 | 14 | public class AnnotationMetadataExtractorTest { 15 | 16 | @Test 17 | public void should_extract_entity_class_from_dao_annotation() { 18 | // given 19 | AnnotationMetadataExtractor extractor = new AnnotationMetadataExtractor(); 20 | 21 | // when 22 | DaoEntity result = extractor.extract(DaoInterface.class); 23 | 24 | // then 25 | assertNotNull(result); 26 | assertEquals(Simple.class, result.getEntityClass()); 27 | assertEquals(Long.class, result.getPrimaryClass()); 28 | } 29 | 30 | @Test 31 | public void should_throw_excption_when_annotation_with_entity_class_not_present() { 32 | // given 33 | AnnotationMetadataExtractor extractor = new AnnotationMetadataExtractor(); 34 | 35 | // when 36 | DaoEntity result = extractor.extract(NoEntityPresentDao.class); 37 | 38 | // then 39 | assertNull(result); 40 | } 41 | 42 | @Test 43 | public void should_throw_exception_when_annotation_with_non_entity_class() { 44 | // given 45 | AnnotationMetadataExtractor extractor = new AnnotationMetadataExtractor(); 46 | 47 | // when 48 | DaoEntity result = extractor.extract(NonEntityDao.class); 49 | 50 | // then 51 | assertNull(result); 52 | } 53 | 54 | @Dao 55 | private static class NoEntityPresentDao { 56 | } 57 | 58 | @Dao(Object.class) 59 | private static class NonEntityDao { 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /faces/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | cdi-query-parent 6 | com.ctp.cdi.query 7 | 1.0.0.Alpha6-SNAPSHOT 8 | ../pom.xml 9 | 10 | 11 | cdi-query-faces 12 | 13 | CDI Query Faces 14 | ${project.parent.url} 15 | 16 | 17 | 18 | 19 | com.ctp.cdi.query 20 | cdi-query-api 21 | 22 | 23 | 24 | javax.enterprise 25 | cdi-api 26 | provided 27 | 28 | 29 | org.jboss.spec.javax.faces 30 | jboss-jsf-api_2.0_spec 31 | provided 32 | 33 | 34 | org.jboss.spec.javax.annotation 35 | jboss-annotations-api_1.1_spec 36 | provided 37 | 38 | 39 | 40 | 41 | cdi-query-faces 42 | 43 | 44 | maven-compiler-plugin 45 | 46 | 1.6 47 | 1.6 48 | UTF-8 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/util/QueryUtils.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.util; 2 | 3 | import java.lang.reflect.Method; 4 | import java.text.MessageFormat; 5 | import java.util.Collection; 6 | 7 | /** 8 | * 9 | * @author thomashug 10 | */ 11 | public final class QueryUtils { 12 | 13 | private QueryUtils() { 14 | } 15 | 16 | private static final String KEYWORD_SPLITTER = "({0})(?=[A-Z])"; 17 | 18 | public static String[] splitByKeyword(String query, String keyword) { 19 | return query.split(MessageFormat.format(KEYWORD_SPLITTER, keyword)); 20 | } 21 | 22 | public static String uncapitalize(String value) { 23 | if (isEmpty(value)) { 24 | return null; 25 | } 26 | if (value.length() == 1) { 27 | return value.toLowerCase(); 28 | } 29 | return value.substring(0, 1).toLowerCase() + value.substring(1); 30 | } 31 | 32 | public static boolean isEmpty(String text) { 33 | return text == null || "".equals(text); 34 | } 35 | 36 | public static boolean isNotEmpty(String text) { 37 | return !isEmpty(text); 38 | } 39 | 40 | public static boolean isEmpty(Collection collection) { 41 | return collection == null || collection.isEmpty(); 42 | } 43 | 44 | public static boolean isEmpty(Object[] array) { 45 | return array == null || array.length == 0; 46 | } 47 | 48 | public static boolean isString(Object value) { 49 | return value != null && value instanceof String; 50 | } 51 | 52 | public static boolean contains(Class clazz, Method method) { 53 | return extract(clazz, method) != null; 54 | } 55 | 56 | public static Method extract(Class clazz, Method method) { 57 | try { 58 | String name = method.getName(); 59 | return clazz.getMethod(name, method.getParameterTypes()); 60 | } catch (NoSuchMethodException e) { 61 | return null; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleCriteriaDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import com.ctp.cdi.query.AbstractEntityDao; 6 | import com.ctp.cdi.query.criteria.CriteriaSupport; 7 | import com.ctp.cdi.query.test.domain.Simple; 8 | import com.ctp.cdi.query.test.domain.Simple_; 9 | 10 | public abstract class SimpleCriteriaDao extends AbstractEntityDao 11 | implements CriteriaSupport { 12 | 13 | public List queryByCriteria(String name, Boolean enabled, Integer from, Integer to) { 14 | return criteria() 15 | .eq(Simple_.name, name) 16 | .eq(Simple_.enabled, enabled) 17 | .between(Simple_.counter, from, to) 18 | .getResultList(); 19 | } 20 | 21 | @SuppressWarnings("unchecked") 22 | public Statistics queryWithSelect(String name) { 23 | return criteria() 24 | .select(Statistics.class, avg(Simple_.counter), count(Simple_.counter)) 25 | .eq(Simple_.name, name) 26 | .getSingleResult(); 27 | } 28 | 29 | @SuppressWarnings("unchecked") 30 | public Object[] queryWithSelectAggregateReturnArray(String name) { 31 | return criteria() 32 | .select(min(Simple_.counter), max(Simple_.counter), 33 | currDate(), currTime(), currTStamp()) 34 | .eq(Simple_.name, name) 35 | .createQuery() 36 | .getSingleResult(); 37 | } 38 | 39 | @SuppressWarnings("unchecked") 40 | public List queryWithSelectAttributes(String name) { 41 | return criteria() 42 | .select(attribute(Simple_.name), 43 | upper(Simple_.name), lower(Simple_.name), 44 | substring(Simple_.name, 2), substring(Simple_.name, 2, 2)) 45 | .eq(Simple_.name, name) 46 | .createQuery() 47 | .getResultList(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/criteria/predicate/FetchBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.criteria.predicate; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import javax.persistence.criteria.CriteriaBuilder; 7 | import javax.persistence.criteria.From; 8 | import javax.persistence.criteria.JoinType; 9 | import javax.persistence.criteria.Path; 10 | import javax.persistence.criteria.Predicate; 11 | import javax.persistence.metamodel.PluralAttribute; 12 | import javax.persistence.metamodel.SingularAttribute; 13 | 14 | public class FetchBuilder implements PredicateBuilder

{ 15 | 16 | final JoinType joinType; 17 | 18 | SingularAttribute singular; 19 | PluralAttribute plural; 20 | 21 | public FetchBuilder(SingularAttribute singular, JoinType joinType) { 22 | this.joinType = joinType; 23 | this.singular = singular; 24 | } 25 | 26 | public FetchBuilder(PluralAttribute plural, JoinType joinType) { 27 | this.joinType = joinType; 28 | this.plural = plural; 29 | } 30 | 31 | @SuppressWarnings("rawtypes") 32 | @Override 33 | public List build(CriteriaBuilder builder, Path

path) { 34 | if (singular != null) { 35 | fetchSingular((From) path); 36 | } else if (plural != null) { 37 | fetchPlural((From) path); 38 | } 39 | return Collections.emptyList(); 40 | } 41 | 42 | @SuppressWarnings({ "rawtypes", "unchecked" }) 43 | private void fetchSingular(From path) { 44 | if (joinType == null) { 45 | path.fetch(singular); 46 | } else { 47 | path.fetch(singular, joinType); 48 | } 49 | } 50 | 51 | @SuppressWarnings({ "rawtypes", "unchecked" }) 52 | private void fetchPlural(From path) { 53 | if (joinType == null) { 54 | path.fetch(plural); 55 | } else { 56 | path.fetch(plural, joinType); 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /api/src/main/java/com/ctp/cdi/query/home/EntityMessage.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.home; 2 | 3 | public class EntityMessage { 4 | 5 | private final MessageType messageType; 6 | private final HomeOperation operation; 7 | private final Object entity; 8 | private final Exception exception; 9 | 10 | public static EntityMessage created(Object entity) { 11 | return new EntityMessage(entity, MessageType.SUCCESS, HomeOperation.CREATE); 12 | } 13 | 14 | public static EntityMessage updated(Object entity) { 15 | return new EntityMessage(entity, MessageType.SUCCESS, HomeOperation.UPDATE); 16 | } 17 | 18 | public static EntityMessage deleted(Object entity) { 19 | return new EntityMessage(entity, MessageType.SUCCESS, HomeOperation.DELETE); 20 | } 21 | 22 | public static EntityMessage failed(Object entity, HomeOperation operation, Exception e) { 23 | return new EntityMessage(entity, MessageType.FAILED, operation, e); 24 | } 25 | 26 | private EntityMessage(Object entity, MessageType messageType, HomeOperation operation) { 27 | this(entity, messageType, operation, null); 28 | } 29 | 30 | private EntityMessage(Object entity, MessageType messageType, HomeOperation operation, Exception exception) { 31 | this.entity = entity; 32 | this.messageType = messageType; 33 | this.operation = operation; 34 | this.exception = exception; 35 | } 36 | 37 | public boolean isSuccess() { 38 | return MessageType.SUCCESS.equals(messageType); 39 | } 40 | 41 | public boolean isFailure() { 42 | return !isSuccess(); 43 | } 44 | 45 | public HomeOperation getOperation() { 46 | return operation; 47 | } 48 | 49 | public Object getEntity() { 50 | return entity; 51 | } 52 | 53 | public Exception getException() { 54 | return exception; 55 | } 56 | 57 | public static enum HomeOperation { 58 | CREATE, UPDATE, DELETE 59 | } 60 | 61 | private static enum MessageType { 62 | SUCCESS, FAILED 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/DescriptorHierarchyBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import java.util.List; 4 | 5 | public final class DescriptorHierarchyBuilder { 6 | 7 | private final List entities; 8 | private final List superClasses; 9 | 10 | private DescriptorHierarchyBuilder(List entities, 11 | List superClasses) { 12 | this.entities = entities; 13 | this.superClasses = superClasses; 14 | } 15 | 16 | public static DescriptorHierarchyBuilder newInstance(List entities, 17 | List superClasses) { 18 | return new DescriptorHierarchyBuilder(entities, superClasses); 19 | } 20 | 21 | public void buildHierarchy() { 22 | for (EntityDescriptor descriptor : entities) { 23 | buildHierarchy(descriptor); 24 | } 25 | } 26 | 27 | private void buildHierarchy(PersistentClassDescriptor descriptor) { 28 | Class superClass = descriptor.getEntityClass().getSuperclass(); 29 | while (superClass != null) { 30 | PersistentClassDescriptor superDescriptor = findPersistentClassDescriptor(superClass); 31 | if (superDescriptor != null) { 32 | if (descriptor.getParent() == null) { 33 | buildHierarchy(superDescriptor); 34 | } 35 | descriptor.setParent(superDescriptor); 36 | return; 37 | } 38 | superClass = superClass.getSuperclass(); 39 | } 40 | } 41 | 42 | private PersistentClassDescriptor findPersistentClassDescriptor(Class superClass) { 43 | for (MappedSuperclassDescriptor descriptor : superClasses) { 44 | if (descriptor.getEntityClass().equals(superClass)){ 45 | return descriptor; 46 | } 47 | } 48 | for (EntityDescriptor descriptor : entities) { 49 | if (descriptor.getEntityClass().equals(superClass)){ 50 | return descriptor; 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | com.ctp.cdi.query 6 | cdi-query-parent 7 | 1.0.0.Alpha6-SNAPSHOT 8 | ../pom.xml 9 | 10 | 11 | cdi-query-api 12 | jar 13 | 14 | CDI Query API 15 | ${project.parent.url} 16 | 17 | 18 | 3.0 19 | 20 | 21 | 22 | ${project.artifactId} 23 | 24 | 25 | 26 | 27 | 28 | javax.enterprise 29 | cdi-api 30 | provided 31 | 32 | 33 | 34 | org.jboss.spec.javax.ejb 35 | jboss-ejb-api_3.1_spec 36 | provided 37 | 38 | 39 | 40 | org.hibernate 41 | hibernate-core 42 | true 43 | provided 44 | 45 | 46 | 47 | com.mysema.querydsl 48 | querydsl-jpa 49 | true 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.apache.maven.plugins 59 | maven-surefire-plugin 60 | 61 | true 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /dist/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.ctp.cdi.query 7 | cdi-query-parent 8 | 1.0.0.Alpha4-SNAPSHOT 9 | ../pom.xml 10 | 11 | 12 | cdi-query-distribution 13 | CDI Query Distribution 14 | Builds a CDI Query release distribution 15 | pom 16 | 17 | 18 | true 19 | 20 | 21 | 22 | 23 | 24 | com.ctp.cdi.query 25 | cdi-query-api 26 | true 27 | 28 | 29 | 30 | com.ctp.cdi.query 31 | cdi-query-api 32 | javadoc 33 | 34 | 35 | 36 | com.ctp.cdi.query 37 | cdi-query-api 38 | sources 39 | true 40 | 41 | 42 | 43 | com.ctp.cdi.query 44 | cdi-query-impl 45 | true 46 | 47 | 48 | 49 | com.ctp.cdi.query 50 | cdi-query-impl 51 | sources 52 | true 53 | 54 | 55 | 56 | 57 | 58 | cdi-query 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-assembly-plugin 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/audit/TimestampsProviderTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | import static org.junit.Assert.assertNull; 5 | import static org.junit.Assert.fail; 6 | 7 | import org.junit.Test; 8 | 9 | import com.ctp.cdi.query.test.domain.AuditedEntity; 10 | import com.ctp.cdi.query.test.domain.Simple; 11 | 12 | public class TimestampsProviderTest { 13 | 14 | @Test 15 | public void should_set_dates_for_creation() { 16 | // given 17 | AuditedEntity entity = new AuditedEntity(); 18 | 19 | // when 20 | new TimestampsProvider().prePersist(entity); 21 | 22 | // then 23 | assertNotNull(entity.getCreated()); 24 | assertNotNull(entity.getModified()); 25 | assertNull(entity.getGregorianModified()); 26 | assertNull(entity.getTimestamp()); 27 | } 28 | 29 | @Test 30 | public void should_set_dates_for_update() { 31 | // given 32 | AuditedEntity entity = new AuditedEntity(); 33 | 34 | // when 35 | new TimestampsProvider().preUpdate(entity); 36 | 37 | // then 38 | assertNull(entity.getCreated()); 39 | assertNotNull(entity.getModified()); 40 | assertNotNull(entity.getGregorianModified()); 41 | assertNotNull(entity.getTimestamp()); 42 | } 43 | 44 | @Test 45 | public void should_not_fail_on_non_audited_entity() { 46 | // given 47 | Simple entity = new Simple(); 48 | 49 | // when 50 | TimestampsProvider provider = new TimestampsProvider(); 51 | provider.prePersist(entity); 52 | provider.preUpdate(entity); 53 | 54 | // then finish the test 55 | } 56 | 57 | @Test(expected = AuditPropertyException.class) 58 | public void should_fail_on_invalid_entity() { 59 | // given 60 | InvalidEntity entity = new InvalidEntity(); 61 | 62 | // when 63 | new TimestampsProvider().prePersist(entity); 64 | 65 | // then 66 | fail(); 67 | } 68 | 69 | private static class InvalidEntity { 70 | 71 | @CreatedOn 72 | @SuppressWarnings("unused") 73 | private String nonTemporal; 74 | 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/extractor/TypeMetadataExtractor.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.extractor; 2 | 3 | import java.io.Serializable; 4 | import java.lang.reflect.ParameterizedType; 5 | import java.lang.reflect.Type; 6 | 7 | import org.jboss.solder.logging.Logger; 8 | 9 | import com.ctp.cdi.query.meta.DaoEntity; 10 | import com.ctp.cdi.query.util.EntityUtils; 11 | 12 | public class TypeMetadataExtractor implements MetadataExtractor { 13 | 14 | private final Logger log = Logger.getLogger(getClass()); 15 | 16 | @Override 17 | public DaoEntity extract(Class daoClass) { 18 | for (Type inf : daoClass.getGenericInterfaces()) { 19 | DaoEntity result = extractFrom(inf); 20 | if (result != null) { 21 | return result; 22 | } 23 | } 24 | DaoEntity result = extractFrom(daoClass.getGenericSuperclass()); 25 | if (result != null) { 26 | return result; 27 | } 28 | for (Type intf : daoClass.getGenericInterfaces()) { 29 | result = extractFrom(intf); 30 | if (result != null) { 31 | return result; 32 | } 33 | } 34 | if (daoClass.getSuperclass() != null) { 35 | return extract(daoClass.getSuperclass()); 36 | } 37 | return null; 38 | } 39 | 40 | @SuppressWarnings("unchecked") 41 | private DaoEntity extractFrom(Type type) { 42 | log.debugv("extractFrom: type = {0}", type); 43 | if (!(type instanceof ParameterizedType)) { 44 | return null; 45 | } 46 | ParameterizedType parametrizedType = (ParameterizedType) type; 47 | Type[] genericTypes = parametrizedType.getActualTypeArguments(); 48 | DaoEntity result = null; 49 | for (Type genericType : genericTypes) { 50 | if (genericType instanceof Class && EntityUtils.isEntityClass((Class) genericType)) { 51 | result = new DaoEntity((Class) genericType); 52 | continue; 53 | } 54 | if (result != null && genericType instanceof Class) { 55 | result.setPrimaryClass((Class) genericType); 56 | return result; 57 | } 58 | } 59 | return result; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/handler/EntityManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.handler; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | 6 | import java.util.List; 7 | 8 | import javax.inject.Inject; 9 | 10 | import org.jboss.arquillian.container.test.api.Deployment; 11 | import org.jboss.arquillian.junit.Arquillian; 12 | import org.jboss.shrinkwrap.api.Archive; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | 16 | import com.ctp.cdi.query.test.domain.Simple; 17 | import com.ctp.cdi.query.test.service.SimpleDaoWithEntityManager; 18 | import com.ctp.cdi.query.test.service.SimpleDaoWithOverriddenEntityManager; 19 | import com.ctp.cdi.query.test.service.Simplistic; 20 | import com.ctp.cdi.query.test.util.TestDeployments; 21 | 22 | @RunWith(Arquillian.class) 23 | public class EntityManagerTest { 24 | 25 | @Deployment 26 | public static Archive deployment() { 27 | return TestDeployments.initDeployment() 28 | .addClasses(SimpleDaoWithEntityManager.class, 29 | SimpleDaoWithOverriddenEntityManager.class, 30 | EntityManagerTestProducer.class, 31 | Simplistic.class); 32 | } 33 | 34 | @Inject 35 | private SimpleDaoWithEntityManager daoWithAnnotation; 36 | 37 | @Inject 38 | private SimpleDaoWithOverriddenEntityManager daoWithInjection; 39 | 40 | @Test 41 | public void should_use_qualified_entity_manager() { 42 | // when 43 | List result = daoWithAnnotation.findByName("testUseQualifiedEntityManager"); 44 | 45 | // then 46 | assertNotNull(result); 47 | assertEquals(0, result.size()); 48 | } 49 | 50 | @Test 51 | public void should_use_injected_entity_manager() { 52 | // when 53 | List result = daoWithInjection.findByName("testUseInjectedEntityManager"); 54 | 55 | // then 56 | assertNotNull(result); 57 | assertEquals(0, result.size()); 58 | } 59 | 60 | @Test 61 | public void should_inject_entity_manager() { 62 | // when 63 | List result = daoWithInjection.findWithEm("testInjectEntityManager"); 64 | 65 | // then 66 | assertNotNull(result); 67 | assertEquals(0, result.size()); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/domain/AuditedEntity.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.domain; 2 | 3 | import java.io.Serializable; 4 | import java.sql.Timestamp; 5 | import java.util.Calendar; 6 | 7 | import javax.persistence.CascadeType; 8 | import javax.persistence.Entity; 9 | import javax.persistence.FetchType; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.Id; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.Temporal; 14 | import javax.persistence.TemporalType; 15 | 16 | import com.ctp.cdi.query.audit.CreatedOn; 17 | import com.ctp.cdi.query.audit.ModifiedBy; 18 | import com.ctp.cdi.query.audit.ModifiedOn; 19 | 20 | @Entity 21 | @SuppressWarnings("serial") 22 | public class AuditedEntity implements Serializable { 23 | 24 | @Id @GeneratedValue 25 | private Long id; 26 | 27 | @Temporal(TemporalType.TIMESTAMP) 28 | @CreatedOn 29 | private Calendar created; 30 | 31 | private String name; 32 | 33 | @ModifiedBy 34 | private String changer; 35 | 36 | @ModifiedBy 37 | @ManyToOne(targetEntity = Principal.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 38 | private Principal principal; 39 | 40 | @Temporal(TemporalType.TIME) 41 | @ModifiedOn(onCreate = true) 42 | private java.util.Date modified; 43 | 44 | @Temporal(TemporalType.DATE) 45 | @ModifiedOn 46 | private Calendar gregorianModified; 47 | 48 | @ModifiedOn 49 | private Timestamp timestamp; 50 | 51 | public AuditedEntity() {} 52 | 53 | public Long getId() { 54 | return id; 55 | } 56 | 57 | public void setId(Long id) { 58 | this.id = id; 59 | } 60 | 61 | public Calendar getCreated() { 62 | return created; 63 | } 64 | 65 | public java.util.Date getModified() { 66 | return modified; 67 | } 68 | 69 | public Calendar getGregorianModified() { 70 | return gregorianModified; 71 | } 72 | 73 | public String getName() { 74 | return name; 75 | } 76 | 77 | public void setName(String name) { 78 | this.name = name; 79 | } 80 | 81 | public Timestamp getTimestamp() { 82 | return timestamp; 83 | } 84 | 85 | public String getChanger() { 86 | return changer; 87 | } 88 | 89 | public void setChanger(String changer) { 90 | this.changer = changer; 91 | } 92 | 93 | public Principal getPrincipal() { 94 | return principal; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/meta/unit/PersistenceUnits.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import java.io.IOException; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.ctp.cdi.query.meta.DaoEntity; 8 | 9 | public final class PersistenceUnits { 10 | 11 | private static PersistenceUnits instance = new PersistenceUnits(); 12 | 13 | private List persistenceUnits = Collections.emptyList(); 14 | 15 | private PersistenceUnits() { 16 | } 17 | 18 | public static PersistenceUnits instance() { 19 | return instance; 20 | } 21 | 22 | public void init() { 23 | persistenceUnits = readPersistenceXmls(); 24 | } 25 | 26 | public boolean isEntity(Class entityClass) { 27 | return find(entityClass) != null; 28 | } 29 | 30 | public String primaryKeyField(Class entityClass) { 31 | EntityDescriptor entity = find(entityClass); 32 | if (entity != null) { 33 | return entity.getId(); 34 | } 35 | return null; 36 | } 37 | 38 | public Class primaryKeyIdClass(Class entityClass) { 39 | EntityDescriptor entity = find(entityClass); 40 | if (entity != null && entity.getIdClass() != null) { 41 | return entity.getIdClass(); 42 | } 43 | return null; 44 | } 45 | 46 | public String entityName(Class entityClass) { 47 | EntityDescriptor entity = find(entityClass); 48 | if (entity != null) { 49 | return entity.getName(); 50 | } 51 | return null; 52 | } 53 | 54 | public DaoEntity lookupMetadata(Class entityClass) { 55 | EntityDescriptor entity = find(entityClass); 56 | if (entity != null) { 57 | return new DaoEntity(entityClass, entity.getIdClass()); 58 | } 59 | return null; 60 | } 61 | 62 | private List readPersistenceXmls() { 63 | try { 64 | PersistenceUnitReader reader = new PersistenceUnitReader(); 65 | return reader.readAll(); 66 | } catch (IOException e) { 67 | throw new RuntimeException("Failed to read persistence unit info", e); 68 | } 69 | } 70 | 71 | private EntityDescriptor find(Class entityClass) { 72 | for (PersistenceUnit unit : persistenceUnits) { 73 | EntityDescriptor entity = unit.find(entityClass); 74 | if (entity != null) { 75 | return entity; 76 | } 77 | } 78 | return null; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/test/service/SimpleDao.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.test.service; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.EntityManager; 6 | import javax.persistence.LockModeType; 7 | 8 | import com.ctp.cdi.query.AbstractEntityDao; 9 | import com.ctp.cdi.query.FirstResult; 10 | import com.ctp.cdi.query.MaxResults; 11 | import com.ctp.cdi.query.Modifying; 12 | import com.ctp.cdi.query.Query; 13 | import com.ctp.cdi.query.QueryParam; 14 | import com.ctp.cdi.query.QueryResult; 15 | import com.ctp.cdi.query.test.domain.Simple; 16 | 17 | public abstract class SimpleDao extends AbstractEntityDao { 18 | 19 | public List implementedQueryByName(String name) { 20 | String query = "select s from Simple s where s.name = :name"; 21 | return entityManager().createQuery(query, Simple.class) 22 | .setParameter("name", name) 23 | .getResultList(); 24 | } 25 | 26 | @Query(named = Simple.BY_NAME_ENABLED, max = 1) 27 | public abstract List findByNamedQueryIndexed(String name, Boolean enabled); 28 | 29 | @Query(named = Simple.BY_NAME_ENABLED) 30 | public abstract List findByNamedQueryRestricted(String name, Boolean enabled, 31 | @MaxResults int max, @FirstResult Integer first); 32 | 33 | @Query(named = Simple.BY_ID, lock = LockModeType.PESSIMISTIC_WRITE) 34 | public abstract Simple findByNamedQueryNamed( 35 | @QueryParam("id") Long id, @QueryParam("enabled") Boolean enabled); 36 | 37 | @Query("select s from Simple s where s.name = ?1") 38 | public abstract Simple findByQuery(String name); 39 | 40 | @Query("select count(s) from Simple s where s.name = ?1") 41 | public abstract Long findCountByQuery(String name); 42 | 43 | public abstract Simple findByNameAndEnabled(String name, Boolean enabled); 44 | 45 | public abstract List findByOrderByCounterAscIdDesc(); 46 | 47 | @Query(sql = "SELECT * from SIMPLE_TABLE s WHERE s.name = ?1") 48 | public abstract List findWithNative(String name); 49 | 50 | @Modifying @Query("update Simple as s set s.name = ?1 where s.id = ?2") 51 | public abstract int updateNameForId(String name, Long id); 52 | 53 | @Query(named = Simple.BY_NAME_LIKE) 54 | public abstract QueryResult queryResultWithNamed(String name); 55 | 56 | public abstract QueryResult findByName(String name); 57 | 58 | @Override 59 | protected abstract EntityManager entityManager(); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /docs/src/main/docbook/en-US/query-preface.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Introduction 7 | 8 | The DAO pattern (Data Access Object) used to be one of the core J2EE patterns and could be found in most 9 | enterprise applications reading and writing data to persistent stores. While the Java Persistence API (JPA) 10 | as part of Java EE 5+ has replaced many aspects of the DAO pattern, it is still a good approach to centralize 11 | complex query logic related to specific entities. 12 | 13 | 14 | The CDI Query module is intended to help you simplifying your DAO layer. While you will have complex queries 15 | in a DAO requiring your full attention, there will also be many simple ones often requiring repetitive code and 16 | cluttering your DAO. This is where the CDI query module will help you keeping your DAO lean so you can focus 17 | on the though things. The code sample below will give you a quick overview on the common usage scenarios of the 18 | CDI Query module: 19 | 20 | { 21 | 22 | List findByAgeBetweenAndGender(int minAge, int maxAge, Gender gender); 23 | 24 | @Query("select p from Person p where p.ssn = ?1") 25 | Person findBySSN(String ssn); 26 | 27 | @Query(named=Person.BY_FULL_NAME) 28 | Person findByFullName(String firstName, String lastName); 29 | 30 | }]]> 31 | 32 | As you see in the sample, there are several usage scenarios outlined here: 33 | 34 | 35 | Declare a method which executes a query by simply translating its name and parameters into a query. 36 | 37 | 38 | Declare a method which automatically executes a given JPQL query string with parameters. 39 | 40 | 41 | Declare a method which automatically executes a named query with parameters. 42 | 43 | 44 | The implementation of the method is done automatically by the CDI Query module. A client can declare 45 | a dependency to the interface only. The details on how to use those features are outlines in the 46 | following chapters. 47 | 48 | 49 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/AnnotatedQueryBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder; 2 | 3 | import static com.ctp.cdi.query.util.QueryUtils.isNotEmpty; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | import javax.persistence.EntityManager; 8 | 9 | import com.ctp.cdi.query.Query; 10 | import com.ctp.cdi.query.handler.CdiQueryInvocationContext; 11 | import com.ctp.cdi.query.meta.MethodType; 12 | import com.ctp.cdi.query.meta.QueryInvocation; 13 | import com.ctp.cdi.query.param.Parameters; 14 | import com.ctp.cdi.query.util.jpa.QueryStringExtractorFactory; 15 | 16 | /** 17 | * Create the query based on method annotations. 18 | * @author thomashug 19 | */ 20 | @QueryInvocation(MethodType.ANNOTATED) 21 | public class AnnotatedQueryBuilder extends QueryBuilder { 22 | 23 | private final QueryStringExtractorFactory factory = new QueryStringExtractorFactory(); 24 | 25 | @Override 26 | public Object execute(CdiQueryInvocationContext context) { 27 | Method method = context.getMethod(); 28 | Query query = method.getAnnotation(Query.class); 29 | javax.persistence.Query jpaQuery = createJpaQuery(query, context); 30 | return context.executeQuery(jpaQuery); 31 | } 32 | 33 | private javax.persistence.Query createJpaQuery(Query query, CdiQueryInvocationContext context) { 34 | EntityManager entityManager = context.getEntityManager(); 35 | Parameters params = context.getParams(); 36 | javax.persistence.Query result = null; 37 | if (isNotEmpty(query.named())) { 38 | if (!context.hasQueryStringPostProcessors()) { 39 | result = params.applyTo(entityManager.createNamedQuery(query.named())); 40 | } else { 41 | javax.persistence.Query namedQuery = entityManager.createNamedQuery(query.named()); 42 | String named = factory.select(namedQuery).extractFrom(namedQuery); 43 | String jpqlQuery = context.applyQueryStringPostProcessors(named); 44 | result = params.applyTo(entityManager.createQuery(jpqlQuery)); 45 | } 46 | } else if (isNotEmpty(query.sql())) { 47 | String jpqlQuery = context.applyQueryStringPostProcessors(query.sql()); 48 | result = params.applyTo(entityManager.createNativeQuery(jpqlQuery)); 49 | } else { 50 | String jpqlQuery = context.applyQueryStringPostProcessors(query.value()); 51 | context.setQueryString(jpqlQuery); 52 | result = params.applyTo(entityManager.createQuery(jpqlQuery)); 53 | } 54 | return applyRestrictions(context, result); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/audit/PrincipalProvider.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.audit; 2 | 3 | import java.util.Collections; 4 | import java.util.Set; 5 | 6 | import javax.enterprise.inject.spi.Bean; 7 | import javax.enterprise.inject.spi.BeanManager; 8 | import javax.inject.Inject; 9 | 10 | import org.jboss.solder.properties.Property; 11 | import org.jboss.solder.properties.query.AnnotatedPropertyCriteria; 12 | import org.jboss.solder.properties.query.PropertyQueries; 13 | import org.jboss.solder.properties.query.PropertyQuery; 14 | import org.jboss.solder.reflection.AnnotationInstanceProvider; 15 | 16 | class PrincipalProvider extends AuditProvider { 17 | 18 | @Inject 19 | private BeanManager manager; 20 | 21 | @Override 22 | public void prePersist(Object entity) { 23 | updatePrincipal(entity); 24 | } 25 | 26 | @Override 27 | public void preUpdate(Object entity) { 28 | updatePrincipal(entity); 29 | } 30 | 31 | private void updatePrincipal(Object entity) { 32 | PropertyQuery query = PropertyQueries.createQuery(entity.getClass()) 33 | .addCriteria(new AnnotatedPropertyCriteria(ModifiedBy.class)); 34 | for (Property property : query.getWritableResultList()) { 35 | setProperty(entity, property); 36 | } 37 | } 38 | 39 | private void setProperty(Object entity, Property property) { 40 | try { 41 | Object value = resolvePrincipal(entity, property); 42 | property.setValue(entity, value); 43 | log.debugv("Updated {0} with {1}", propertyName(entity, property), value); 44 | } catch (Exception e) { 45 | throw new AuditPropertyException("Failed to write principal to " + 46 | propertyName(entity, property), e); 47 | } 48 | } 49 | 50 | private Object resolvePrincipal(Object entity, Property property) { 51 | AnnotationInstanceProvider provider = new AnnotationInstanceProvider(); 52 | CurrentUser principal = provider.get(CurrentUser.class, Collections.emptyMap()); 53 | Class propertyClass = property.getJavaClass(); 54 | Set> beans = manager.getBeans(propertyClass, principal); 55 | if (!beans.isEmpty() && beans.size() == 1) { 56 | Bean bean = beans.iterator().next(); 57 | Object result = manager.getReference(bean, propertyClass, manager.createCreationalContext(bean)); 58 | return result; 59 | } 60 | throw new IllegalArgumentException("Principal " + (beans.isEmpty() ? "not found" : "not unique") + 61 | " for " + propertyName(entity, property)); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /impl/src/test/java/com/ctp/cdi/query/meta/unit/OrmXmlBasedDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.meta.unit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import javax.enterprise.inject.Produces; 6 | import javax.inject.Inject; 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.PersistenceContext; 9 | 10 | import org.jboss.arquillian.container.test.api.Deployment; 11 | import org.jboss.shrinkwrap.api.Archive; 12 | import org.jboss.shrinkwrap.api.ArchivePaths; 13 | import org.jboss.shrinkwrap.api.ShrinkWrap; 14 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 15 | import org.junit.Test; 16 | 17 | import com.ctp.cdi.query.test.TransactionalTestCase; 18 | import com.ctp.cdi.query.test.domain.mapped.MappedOne; 19 | import com.ctp.cdi.query.test.domain.mapped.MappedThree; 20 | import com.ctp.cdi.query.test.domain.mapped.MappedTwo; 21 | import com.ctp.cdi.query.test.service.MappedOneDao; 22 | import com.ctp.cdi.query.test.util.TestDeployments; 23 | 24 | public class OrmXmlBasedDaoTest extends TransactionalTestCase { 25 | 26 | @Deployment 27 | public static Archive deployment() { 28 | return TestDeployments.initDeployment(".*mapped.*") 29 | .addClasses(MappedOneDao.class) 30 | .addAsLibraries( 31 | ShrinkWrap.create(JavaArchive.class, "domain.jar") 32 | .addClasses(MappedOne.class, MappedTwo.class, MappedThree.class) 33 | .addAsResource("test-custom-orm.xml", ArchivePaths.create("META-INF/custom-orm.xml")) 34 | ) 35 | .addAsWebInfResource("test-mapped-persistence.xml", ArchivePaths.create("classes/META-INF/persistence.xml")) 36 | .addAsWebInfResource("test-default-orm.xml", ArchivePaths.create("classes/META-INF/orm.xml")); 37 | } 38 | 39 | @Produces 40 | @PersistenceContext 41 | private EntityManager entityManager; 42 | 43 | @Inject 44 | private MappedOneDao mappedOneDao; 45 | 46 | @Test 47 | public void should_find_by() { 48 | // given 49 | MappedOne one = createMappedOne("shouldFindBy"); 50 | 51 | // when 52 | MappedOne byPk = mappedOneDao.findBy(one.getId()); 53 | MappedOne byName = mappedOneDao.findByName("shouldFindBy"); 54 | 55 | // then 56 | assertEquals(one.getId(), byPk.getId()); 57 | assertEquals(one.getId(), byName.getId()); 58 | } 59 | 60 | @Override 61 | protected EntityManager getEntityManager() { 62 | return entityManager; 63 | } 64 | 65 | private MappedOne createMappedOne(String name) { 66 | MappedOne result = new MappedOne(name); 67 | entityManager.persist(result); 68 | entityManager.flush(); 69 | return result; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /impl/src/main/java/com/ctp/cdi/query/builder/result/QueryProcessorFactory.java: -------------------------------------------------------------------------------- 1 | package com.ctp.cdi.query.builder.result; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | 6 | import javax.persistence.Query; 7 | 8 | import com.ctp.cdi.query.Modifying; 9 | import com.ctp.cdi.query.QueryResult; 10 | 11 | public final class QueryProcessorFactory { 12 | 13 | private final Method method; 14 | 15 | private QueryProcessorFactory(Method method) { 16 | this.method = method; 17 | } 18 | 19 | public static QueryProcessorFactory newInstance(Method method) { 20 | return new QueryProcessorFactory(method); 21 | } 22 | 23 | public QueryProcessor build() { 24 | if (returns(QueryResult.class)) { 25 | return new NoOpQueryProcessor(); 26 | } 27 | if (returns(List.class)) { 28 | return new ListQueryProcessor(); 29 | } 30 | if (isModifying()) { 31 | return new ExecuteUpdateQueryProcessor(returns(Void.TYPE)); 32 | } 33 | return new SingleResultQueryProcessor(); 34 | } 35 | 36 | private boolean isModifying() { 37 | boolean matchesType = Void.TYPE.equals(method.getReturnType()) || 38 | int.class.equals(method.getReturnType()) || 39 | Integer.class.equals(method.getReturnType()); 40 | return method.isAnnotationPresent(Modifying.class) && matchesType; 41 | } 42 | 43 | private boolean returns(Class clazz) { 44 | return method.getReturnType().isAssignableFrom(clazz); 45 | } 46 | 47 | private static final class ListQueryProcessor implements QueryProcessor { 48 | @Override 49 | public Object executeQuery(Query query) { 50 | return query.getResultList(); 51 | } 52 | } 53 | 54 | private static final class NoOpQueryProcessor implements QueryProcessor { 55 | @Override 56 | public Object executeQuery(Query query) { 57 | return query; 58 | } 59 | } 60 | 61 | private static final class SingleResultQueryProcessor implements QueryProcessor { 62 | @Override 63 | public Object executeQuery(Query query) { 64 | return query.getSingleResult(); 65 | } 66 | } 67 | 68 | private static final class ExecuteUpdateQueryProcessor implements QueryProcessor { 69 | 70 | private final boolean returnsVoid; 71 | 72 | private ExecuteUpdateQueryProcessor(boolean returnsVoid) { 73 | this.returnsVoid = returnsVoid; 74 | } 75 | 76 | @Override 77 | public Object executeQuery(Query query) { 78 | int result = query.executeUpdate(); 79 | if (!returnsVoid) { 80 | return result; 81 | } 82 | return null; 83 | } 84 | } 85 | } 86 | --------------------------------------------------------------------------------