1+ /**
2+ * This Source Code Form is subject to the terms of the Mozilla Public License,
3+ * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+ * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+ * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+ *
7+ * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+ * graphic logo is a trademark of OpenMRS Inc.
9+ */
10+ package org .openmrs .module .reporting .report .service .db ;
11+
12+ import java .io .Serializable ;
13+ import java .sql .PreparedStatement ;
14+ import java .sql .ResultSet ;
15+ import java .sql .SQLException ;
16+ import java .util .HashMap ;
17+ import java .util .Map ;
18+ import java .util .Properties ;
19+
20+ import org .apache .commons .lang .StringUtils ;
21+ import org .hibernate .Hibernate ;
22+ import org .hibernate .HibernateException ;
23+ import org .hibernate .engine .SessionImplementor ;
24+ import org .hibernate .type .Type ;
25+ import org .hibernate .usertype .CompositeUserType ;
26+ import org .hibernate .usertype .ParameterizedType ;
27+ import org .hibernate .usertype .UserType ;
28+ import org .openmrs .api .context .Context ;
29+ import org .openmrs .module .reporting .common .HibernateUtil ;
30+ import org .openmrs .module .reporting .definition .DefinitionContext ;
31+ import org .openmrs .module .reporting .evaluation .Definition ;
32+ import org .openmrs .module .reporting .evaluation .parameter .Mapped ;
33+ import org .openmrs .module .reporting .evaluation .parameter .Parameterizable ;
34+ import org .openmrs .module .reporting .serializer .ReportingSerializer ;
35+
36+ /**
37+ * Custom User-Type for storing Mapped objects in a single table within 2 columns
38+ * This type takes in 2 properties and 1 parameter in the form:
39+ * <pre>
40+ * <property name="reportDefinition">
41+ * <column name="report_definition_uuid"/>
42+ * <column name="report_definition_parameters"/>
43+ * <type name="org.openmrs.module.reporting.report.service.db.MappedDefinitionType">
44+ * <param name="mappedType">org.openmrs.module.reporting.report.definition.ReportDefinition</param>
45+ * </type>
46+ * </property>
47+ * </pre>
48+ */
49+ @ SuppressWarnings ({"rawtypes" , "unchecked" })
50+ public class MappedDefinitionType implements CompositeUserType , ParameterizedType {
51+
52+ /**
53+ * Property via ParameterizedType for storing the type of the Mapped Parameterizable
54+ */
55+ private Class <? extends Definition > mappedType ;
56+
57+ /**
58+ * @see CompositeUserType#returnedClass()
59+ */
60+ public Class returnedClass () {
61+ return Mapped .class ;
62+ }
63+
64+ /**
65+ * @see CompositeUserType#getPropertyNames()
66+ */
67+ public String [] getPropertyNames () {
68+ return new String [] {"definition" , "parameterMappings" };
69+ }
70+
71+ /**
72+ * @see CompositeUserType#getPropertyTypes()
73+ */
74+ public Type [] getPropertyTypes () {
75+ return new Type [] { HibernateUtil .standardType ("STRING" ), HibernateUtil .standardType ("TEXT" ) };
76+ }
77+
78+ /**
79+ * @see CompositeUserType#isMutable()
80+ */
81+ public boolean isMutable () {
82+ return true ;
83+ }
84+
85+ /**
86+ * @see CompositeUserType#getPropertyValue(java.lang.Object, int)
87+ */
88+ public Object getPropertyValue (Object component , int property ) throws HibernateException {
89+ Mapped m = (Mapped ) component ;
90+ return (property == 0 ? m .getParameterizable () : m .getParameterMappings ());
91+ }
92+
93+ /**
94+ * @see CompositeUserType#setPropertyValue(java.lang.Object, int, java.lang.Object)
95+ */
96+ public void setPropertyValue (Object component , int property , Object value ) throws HibernateException {
97+ Mapped m = (Mapped ) component ;
98+ if (property == 0 ) {
99+ m .setParameterizable ((Parameterizable )value );
100+ }
101+ else {
102+ m .setParameterMappings ((Map )value );
103+ }
104+ }
105+
106+ /**
107+ * @see CompositeUserType#deepCopy(java.lang.Object)
108+ */
109+ public Object deepCopy (Object value ) throws HibernateException {
110+ if (value == null ) return null ;
111+ Mapped toCopy = (Mapped ) value ;
112+ Mapped m = new Mapped ();
113+ m .setParameterizable (toCopy .getParameterizable ());
114+ m .setParameterMappings (new HashMap <String , Object >(toCopy .getParameterMappings ()));
115+ return m ;
116+ }
117+
118+ /**
119+ * @see CompositeUserType#nullSafeGet(ResultSet, String[], SessionImplementor, Object)
120+ */
121+ public Object nullSafeGet (ResultSet rs , String [] names , SessionImplementor session , Object owner ) throws HibernateException , SQLException {
122+ String parameterizableUuid = (String ) HibernateUtil .standardType ("STRING" ).nullSafeGet (rs , names [0 ], session , owner );
123+ if (StringUtils .isEmpty (parameterizableUuid )) { return null ; }
124+ String serializedMappings = (String ) HibernateUtil .standardType ("STRING" ).nullSafeGet (rs , names [1 ], session , owner );
125+ Definition d = DefinitionContext .getDefinitionByUuid (mappedType , parameterizableUuid );
126+ Map <String , Object > mappings = new HashMap <String , Object >();
127+ if (StringUtils .isNotBlank (serializedMappings )) {
128+ try {
129+ mappings = Context .getSerializationService ().deserialize (serializedMappings , Map .class , ReportingSerializer .class );
130+ }
131+ catch (Exception e ) {
132+ throw new HibernateException ("Unable to deserialize parameter mappings for definition" , e );
133+ }
134+ }
135+ return new Mapped (d , mappings );
136+ }
137+
138+ /**
139+ * @see CompositeUserType#nullSafeSet(PreparedStatement, Object, int, SessionImplementor)
140+ */
141+ public void nullSafeSet (PreparedStatement st , Object value , int index , SessionImplementor session ) throws HibernateException , SQLException {
142+ String definitionUuid = null ;
143+ String serializedMappings = null ;
144+ if (value != null ) {
145+ Mapped m = (Mapped ) value ;
146+ if (m .getParameterizable () != null ) {
147+ definitionUuid = m .getParameterizable ().getUuid ();
148+ if (m .getParameterMappings () != null && !m .getParameterMappings ().isEmpty ()) {
149+ try {
150+ serializedMappings = Context .getSerializationService ().serialize (m .getParameterMappings (), ReportingSerializer .class );
151+ }
152+ catch (Exception e ) {
153+ throw new HibernateException ("Unable to serialize mappings for definition" , e );
154+ }
155+ }
156+ }
157+ }
158+ HibernateUtil .standardType ("STRING" ).nullSafeSet (st , definitionUuid , index , session );
159+ HibernateUtil .standardType ("STRING" ).nullSafeSet (st , serializedMappings , index +1 , session );
160+ }
161+
162+ /**
163+ * @see CompositeUserType#replace(Object, Object, SessionImplementor, Object)
164+ */
165+ public Object replace (Object original , Object target , SessionImplementor session , Object owner ) throws HibernateException {
166+ return original ;
167+ }
168+
169+ /**
170+ * @see UserType#equals(Object, Object)
171+ */
172+ public boolean equals (Object x , Object y ) throws HibernateException {
173+ return x != null && x .equals (y );
174+ }
175+
176+ /**
177+ * @see UserType#hashCode(Object)
178+ */
179+ public int hashCode (Object x ) throws HibernateException {
180+ return x .hashCode ();
181+ }
182+
183+ /**
184+ * @see CompositeUserType#disassemble(Object, SessionImplementor)
185+ */
186+ public Serializable disassemble (Object value , SessionImplementor session ) throws HibernateException {
187+ return (Serializable ) deepCopy (value );
188+ }
189+
190+ /**
191+ * @see CompositeUserType#assemble(Serializable, SessionImplementor, Object)
192+ */
193+ public Object assemble (Serializable cached , SessionImplementor session , Object owner ) throws HibernateException {
194+ return deepCopy (cached );
195+ }
196+
197+ /**
198+ * @see ParameterizedType#setParameterValues(Properties)
199+ */
200+ public void setParameterValues (Properties parameters ) {
201+ String mappedTypeStr = parameters .getProperty ("mappedType" );
202+ try {
203+ mappedType = (Class <? extends Definition >)Context .loadClass (mappedTypeStr );
204+ }
205+ catch (Exception e ) {
206+ throw new HibernateException ("Error setting the mappedType property to " + mappedTypeStr , e );
207+ }
208+ }
209+ }
0 commit comments