1   package com.trendmicro.grid.acl.ds.jpa.util;
2   
3   import com.trendmicro.grid.acl.l0.datatypes.FileIdentifier;
4   import static net.sf.tinyjee.util.Assert.assertNotNull;
5   
6   import javax.persistence.EntityManager;
7   import javax.persistence.Query;
8   import javax.persistence.TypedQuery;
9   
10  /**
11   * Is a helper class that configures and caches queries that fetch results by FileIdentifier.
12   * <p/>
13   * Note: Instanes of this class are meant to be short lived for the time of a single transaction.
14   *
15   * @param <T> The type of the expected result.
16   */
17  public class FileQueryConfigurator<T> {
18  
19  	private final EntityManager em;
20  	private final String sha1QueryName;
21  	private final String md5QueryName;
22  	private final String fullQueryName;
23  	private final Class<T> resultType;
24  
25  	private Query md5Query, sha1Query, fullQuery;
26  
27  	/**
28  	 * Creates a new configurator.
29  	 *
30  	 * @param em			the entitymanager to use for retrieving the queries.
31  	 * @param resultType	the result type of the queries.
32  	 * @param queryBaseName the common base name for both queries.
33  	 */
34  	public FileQueryConfigurator(EntityManager em, Class<T> resultType, String queryBaseName) {
35  		this(em, resultType, queryBaseName.concat("ByMD5"), queryBaseName.concat("BySHA1"), queryBaseName.concat("BySHA1AndMD5"));
36  	}
37  
38  	/**
39  	 * Creates a new configurator.
40  	 *
41  	 * @param em			the entitymanager to use for retrieving the queries.
42  	 * @param resultType	the result type of the queries.
43  	 * @param sha1QueryName	 the name of the named sha1-only query
44  	 * @param fullQueryName the name of the named sha1+md5 query.
45  	 */
46  	public FileQueryConfigurator(EntityManager em, Class<T> resultType, String md5QueryName, String sha1QueryName, String fullQueryName) {
47  		this.em = em;
48  		this.resultType = resultType;
49  		this.md5QueryName = md5QueryName;
50  		this.sha1QueryName = sha1QueryName;
51  		this.fullQueryName = fullQueryName;
52  	}
53  
54  	/**
55  	 * Returns the configured query.
56  	 *
57  	 * @param file the identifier specifying the file to ask for.
58  	 * @return the configured query.
59  	 */
60  	@SuppressWarnings("unchecked")
61  	public TypedQuery<T> getQuery(FileIdentifier file) {
62  		if (resultType == null) throw new IllegalStateException("Result type cannot be 'null' for typed queries.");
63  
64  		return (TypedQuery<T>) getUntypedQuery(file);
65  	}
66  
67  	/**
68  	 * Returns the configured query.
69  	 *
70  	 * @param file the identifier specifying the file to ask for.
71  	 * @return the configured query.
72  	 */
73  	public Query getUntypedQuery(FileIdentifier file) {
74  		assertNotNull("FileIdentifier", file);
75  
76  		final Query q;
77  		final byte[] md5 = file.getMD5Hash();
78  		final byte[] sha1 = file.getSHA1Hash();
79  
80  		if (sha1 == null) {
81  			if (md5Query == null) {
82  				if (resultType == null)
83  					md5Query = em.createNamedQuery(md5QueryName).setMaxResults(1);
84  				else
85  					md5Query = em.createNamedQuery(md5QueryName, resultType).setMaxResults(1);
86  			}
87  			q = md5Query.setParameter("md5", md5);
88  		} else if (md5 == null) {
89  			if (sha1Query == null) {
90  				if (resultType == null)
91  					sha1Query = em.createNamedQuery(sha1QueryName).setMaxResults(1);
92  				else
93  					sha1Query = em.createNamedQuery(sha1QueryName, resultType).setMaxResults(1);
94  			}
95  			q = sha1Query.setParameter("sha1", sha1);
96  		} else {
97  			if (fullQuery == null) {
98  				if (resultType == null)
99  					fullQuery = em.createNamedQuery(fullQueryName).setMaxResults(1);
100 				else
101 					fullQuery = em.createNamedQuery(fullQueryName, resultType).setMaxResults(1);
102 			}
103 			q = fullQuery.setParameter("md5", md5).setParameter("sha1", sha1);
104 		}
105 
106 		return q;
107 	}
108 }