View Javadoc
1   package ca.uhn.fhir.jpa.entity;
2   
3   /*
4    * #%L
5    * HAPI FHIR JPA Server
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import ca.uhn.fhir.model.api.IQueryParameterType;
24  import ca.uhn.fhir.util.UrlUtil;
25  import com.google.common.base.Charsets;
26  import com.google.common.hash.HashCode;
27  import com.google.common.hash.HashFunction;
28  import com.google.common.hash.Hasher;
29  import com.google.common.hash.Hashing;
30  import org.hibernate.search.annotations.ContainedIn;
31  import org.hibernate.search.annotations.Field;
32  
33  import javax.persistence.*;
34  import java.io.Serializable;
35  import java.util.Date;
36  
37  @MappedSuperclass
38  public abstract class BaseResourceIndexedSearchParam implements Serializable {
39  	/** Don't change this without careful consideration. You will break existing hashes! */
40  	private static final HashFunction HASH_FUNCTION = Hashing.murmur3_128(0);
41  	/** Don't make this public 'cause nobody better touch it! */
42  	private static final byte[] DELIMITER_BYTES = "|".getBytes(Charsets.UTF_8);
43  
44  	static final int MAX_SP_NAME = 100;
45  
46  	private static final long serialVersionUID = 1L;
47  
48  	// TODO: make this nullable=false and a primitive (written may 2017)
49  	@Field()
50  	@Column(name = "SP_MISSING", nullable = true)
51  	private Boolean myMissing = Boolean.FALSE;
52  
53  	@Field
54  	@Column(name = "SP_NAME", length = MAX_SP_NAME, nullable = false)
55  	private String myParamName;
56  
57  	@ManyToOne(optional = false)
58  	@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID")
59  	@ContainedIn
60  	private ResourceTable myResource;
61  
62  	@Column(name = "RES_ID", insertable = false, updatable = false)
63  	private Long myResourcePid;
64  
65  	@Field()
66  	@Column(name = "RES_TYPE", nullable = false)
67  	private String myResourceType;
68  
69  	@Field()
70  	@Column(name = "SP_UPDATED", nullable = true) // TODO: make this false after HAPI 2.3
71  	@Temporal(TemporalType.TIMESTAMP)
72  	private Date myUpdated;
73  
74  	protected abstract Long getId();
75  
76  	public String getParamName() {
77  		return myParamName;
78  	}
79  
80  	public void setParamName(String theName) {
81  		clearHashes();
82  		myParamName = theName;
83  	}
84  
85  	/**
86  	 * Subclasses may override
87  	 */
88  	protected void clearHashes() {
89  		// nothing
90  	}
91  
92  	public ResourceTable getResource() {
93  		return myResource;
94  	}
95  
96  	public BaseResourceIndexedSearchParam setResource(ResourceTable theResource) {
97  		clearHashes();
98  		myResource = theResource;
99  		myResourceType = theResource.getResourceType();
100 		return this;
101 	}
102 
103 	public Long getResourcePid() {
104 		return myResourcePid;
105 	}
106 
107 	public String getResourceType() {
108 		return myResourceType;
109 	}
110 
111 	public Date getUpdated() {
112 		return myUpdated;
113 	}
114 
115 	public void setUpdated(Date theUpdated) {
116 		myUpdated = theUpdated;
117 	}
118 
119 	public boolean isMissing() {
120 		return Boolean.TRUE.equals(myMissing);
121 	}
122 
123 	public BaseResourceIndexedSearchParam setMissing(boolean theMissing) {
124 		myMissing = theMissing;
125 		return this;
126 	}
127 
128 	public abstract IQueryParameterType toQueryParameterType();
129 
130 	/**
131 	 * Applies a fast and consistent hashing algorithm to a set of strings
132 	 */
133 	static long hash(String... theValues) {
134 		Hasher hasher = HASH_FUNCTION.newHasher();
135 
136 		for (String next : theValues) {
137 			if (next == null) {
138 				hasher.putByte((byte) 0);
139 			} else {
140 				next = UrlUtil.escapeUrlParam(next);
141 				byte[] bytes = next.getBytes(Charsets.UTF_8);
142 				hasher.putBytes(bytes);
143 			}
144 			hasher.putBytes(DELIMITER_BYTES);
145 		}
146 
147 		HashCode hashCode = hasher.hash();
148 		return hashCode.asLong();
149 	}
150 
151 
152 }