View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service.impl;
17  
18  import org.junit.Assert;
19  import org.junit.BeforeClass;
20  import org.junit.Test;
21  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoaderTestUtils;
22  import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
23  import org.kuali.rice.krad.data.provider.annotation.SerializationContext;
24  import org.kuali.rice.krad.data.provider.annotation.Serialized;
25  import org.kuali.rice.krad.maintenance.MaintainableImpl;
26  import org.kuali.rice.krad.maintenance.MaintenanceDocumentBase;
27  import org.kuali.rice.krad.service.KRADServiceLocator;
28  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
29  import org.kuali.rice.krad.service.LegacyDataAdapter;
30  
31  import javax.persistence.Transient;
32  import java.io.Serializable;
33  
34  import static org.mockito.Mockito.*;
35  
36  /**
37   * Test to verify that our custom {@link org.kuali.rice.krad.data.provider.annotation.Serialized} annotation as well
38   * as {@link javax.persistence.Transient} influence the metadata and effect serialization of fields as intended.
39   *
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  public class MaintenanceDocumentSerializationTest {
43  
44      // fields are default visibility as this class is extended
45  
46      static final TestKradChildOjb child = new TestKradChildOjb("child", "content1", "content2", "content3", "content4", "content5", "content6");
47      static final TestKradDataObj dataObject = new TestKradDataObj("dataObject", child, child, child, child, child, child);
48      static final XmlObjectSerializerServiceImpl xmlObjectSerializerServiceImpl = new XmlObjectSerializerServiceImpl();
49      static LegacyDataAdapter mockLegacyDataAdapter;
50  
51      /**
52       * Wire up services and mocks, and plunk them the GRL as needed to get the maintenance document serialization
53       * functionality up and working.
54       */
55      @BeforeClass
56      public static void setupServices() {
57          // create a mock LegacyDataAdapter that will answer all the questions it is asked appropriately
58          mockLegacyDataAdapter = mock(LegacyDataAdapter.class);
59          when(mockLegacyDataAdapter.areNotesSupported(any(Class.class))).thenReturn(Boolean.FALSE);
60          when(mockLegacyDataAdapter.isProxied(anyObject())).thenReturn(Boolean.FALSE);
61  
62          xmlObjectSerializerServiceImpl.setLegacyDataAdapter(mockLegacyDataAdapter);
63  
64          // create a DataObjectSerializerServiceImpl that will be used in KRAD to determine whether a given field is serialized
65          DataObjectSerializerServiceImpl dataObjectSerializerService = new DataObjectSerializerServiceImpl();
66          dataObjectSerializerService.setLegacyDataAdapter(mockLegacyDataAdapter);
67  
68          // put needed mock and hand wired services into the GRL
69          GlobalResourceLoaderTestUtils.addMockService(KRADServiceLocatorWeb.LEGACY_DATA_ADAPTER, mockLegacyDataAdapter);
70          GlobalResourceLoaderTestUtils.addMockService(KRADServiceLocator.KRAD_SERIALIZER_SERVICE, dataObjectSerializerService);
71          GlobalResourceLoaderTestUtils.addMockService(KRADServiceLocator.XML_OBJECT_SERIALIZER_SERVICE, xmlObjectSerializerServiceImpl);
72      }
73  
74      /**
75       * Run the serialization / deserialization cycle on the maintenance doc and verify that the annotations properly
76       * control which fields are serialized (and thus survive that cycle).
77       */
78      @Test
79      public void kradSerializationAnnotationTest() {
80          // rig our maintainable up with the minimal parts needed to test serialization
81          MaintainableImpl maintainable = new MaintainableImpl();
82          maintainable.setLegacyDataAdapter(mockLegacyDataAdapter);
83          maintainable.setDataObject(dataObject);
84  
85          MaintenanceDocumentBase kradMaintenanceDoc = new MaintenanceDocumentBase();
86  
87          // use our maintenance doc to serialize / deserialize the data object
88          kradMaintenanceDoc.setNewMaintainableObject(maintainable);
89          kradMaintenanceDoc.populateXmlDocumentContentsFromMaintainables();
90          kradMaintenanceDoc.populateMaintainablesFromXmlDocumentContents();
91          TestKradDataObj reconstitutedDataObject =
92                  (TestKradDataObj) kradMaintenanceDoc.getNewMaintainableObject().getDataObject();
93  
94          // verify that the fields we expected to survive did, and otherwise are null
95  
96          Assert.assertNull("annotated to disable serialization, should be null", reconstitutedDataObject.getChild2());
97          Assert.assertNull("annotated as transient with nothing to override, should be null", reconstitutedDataObject.getChild4());
98          Assert.assertNull("annotated as transient and to disable serialization, should be null", reconstitutedDataObject.getChild5());
99  
100         Assert.assertEquals("This field annotated to disable serialization for a different SerializationType must survive",
101                 dataObject.getName(), reconstitutedDataObject.getName());
102 
103         Assert.assertNotNull("Child object with no field annotations, it must survive",
104                 reconstitutedDataObject.getChild1());
105         Assert.assertNotNull("Annotated to be serialized, it must survive", reconstitutedDataObject.getChild3());
106         Assert.assertNotNull("Transient, but annotated to be serialized, it must survive", reconstitutedDataObject.getChild6());
107 
108         // verify that the annotations on the child object were respected too
109 
110         Assert.assertNull("annotated to disable serialization, should be null", reconstitutedDataObject.getChild1().getContent2());
111         Assert.assertNull("annotated as transient with nothing to override, should be null", reconstitutedDataObject.getChild1().getContent4());
112         Assert.assertNull("annotated as transient and to disable serialization, should be null", reconstitutedDataObject.getChild1().getContent5());
113 
114         Assert.assertEquals("with no field annotations, it must survive", child.getContent1(), reconstitutedDataObject.getChild1().getContent1());
115         Assert.assertEquals("Annotated to be serialized, it must survive", child.getContent3(), reconstitutedDataObject.getChild1().getContent3());
116         Assert.assertEquals("Transient, but annotated to be serialized, it must survive", child.getContent6(),
117                 reconstitutedDataObject.getChild1().getContent6());
118     }
119 }
120 
121 /**
122  * Test class with fields that have all the permutations of @Transient, @Serialized(enabled=true)
123  * and @Serialized(enabled=false) to verify the functionality in each case.
124  */
125 class TestKradDataObj extends PersistableBusinessObjectBase implements Serializable {
126 
127     // annotated, but for a different SerializationType -- should be ignored
128     @Serialized(enabled = false, forContexts = { /* SerializationContext.WORKFLOW */ })
129     private String name;
130 
131     // a child object without any special annotations.  Should survive.
132     private TestKradChildOjb child1;
133 
134     // a child object that is annotated to not be serialized in our specific SerializationType.  Should not survive.
135     @Serialized(enabled = false, forContexts = { SerializationContext.MAINTENANCE })
136     private TestKradChildOjb child2;
137 
138 
139     // a child object that is annotated to be serialized.  Should survive.
140     @Serialized(enabled = true)
141     private TestKradChildOjb child3;
142 
143     // a child object that is marked JPA transient.  Should not survive.
144     @Transient
145     private TestKradChildOjb child4;
146 
147     // a child object that is marked JPA transient, and is annotated to not be serialized.  Should not survive.
148     @Serialized(enabled = false)
149     @Transient
150     private TestKradChildOjb child5;
151 
152     // a child object that is marked JPA transient, and is annotated to be serialized for all SerializationTypes (which
153     // is the default SerializationType).  Should survive.
154     @Serialized(enabled = true, forContexts = { SerializationContext.ALL })
155     @Transient
156     private TestKradChildOjb child6;
157 
158     TestKradDataObj(String name, TestKradChildOjb child1, TestKradChildOjb child2, TestKradChildOjb child3,
159             TestKradChildOjb child4, TestKradChildOjb child5, TestKradChildOjb child6) {
160         this.name = name;
161         this.child1 = child1;
162         this.child2 = child2;
163         this.child3 = child3;
164         this.child4 = child4;
165         this.child5 = child5;
166         this.child6 = child6;
167     }
168 
169     public String getName() {
170         return name;
171     }
172 
173     public TestKradChildOjb getChild1() {
174         return child1;
175     }
176 
177     public TestKradChildOjb getChild2() {
178         return child2;
179     }
180 
181     public TestKradChildOjb getChild3() {
182         return child3;
183     }
184 
185     public TestKradChildOjb getChild4() {
186         return child4;
187     }
188 
189     public TestKradChildOjb getChild5() {
190         return child5;
191     }
192 
193     public TestKradChildOjb getChild6() {
194         return child6;
195     }
196 }
197 
198 /**
199  * Test class with fields that have all the permutations of @Transient, @Serialized(enabled=true)
200  * and @Serialized(enabled=false) to verify the functionality in each case.
201  */
202 class TestKradChildOjb implements Serializable {
203 
204     private String name;
205 
206     private String content1;
207 
208     @Serialized(enabled = false)
209     private String content2;
210 
211     @Serialized(enabled = true)
212     private String content3;
213 
214     @Transient
215     private String content4;
216 
217     @Serialized(enabled = false)
218     @Transient
219     private String content5;
220 
221     @Serialized(enabled = true)
222     @Transient
223     private String content6;
224 
225     TestKradChildOjb(String name, String content1, String content2, String content3, String content4, String content5,
226             String content6) {
227         this.name = name;
228         this.content1 = content1;
229         this.content2 = content2;
230         this.content3 = content3;
231         this.content4 = content4;
232         this.content5 = content5;
233         this.content6 = content6;
234     }
235 
236     public String getName() {
237         return name;
238     }
239 
240     public String getContent1() {
241         return content1;
242     }
243 
244     public String getContent2() {
245         return content2;
246     }
247 
248     public String getContent3() {
249         return content3;
250     }
251 
252     public String getContent4() {
253         return content4;
254     }
255 
256     public String getContent5() {
257         return content5;
258     }
259 
260     public String getContent6() {
261         return content6;
262     }
263 }
264 
265