View Javadoc

1   /**
2    * Copyright 2005-2013 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.uif.util;
17  
18  import org.junit.Before;
19  import org.junit.Ignore;
20  import org.junit.Test;
21  import org.kuali.rice.krad.uif.component.Component;
22  import org.kuali.rice.krad.uif.component.ComponentBase;
23  import org.kuali.rice.krad.uif.component.ReferenceCopy;
24  import org.kuali.rice.krad.uif.control.CheckboxControl;
25  import org.kuali.rice.krad.uif.element.DataTable;
26  import org.kuali.rice.krad.uif.field.DataField;
27  import org.kuali.rice.krad.uif.field.FieldBase;
28  import org.kuali.rice.krad.uif.field.InputField;
29  
30  import java.lang.reflect.Field;
31  import java.lang.reflect.ParameterizedType;
32  import java.util.ArrayList;
33  import java.util.Arrays;
34  import java.util.HashMap;
35  import java.util.HashSet;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.Set;
39  
40  import java.lang.reflect.Method;
41  
42  import static junit.framework.Assert.assertEquals;
43  import static junit.framework.Assert.assertTrue;
44  
45  /**
46   * ComponentUtilsTest tests various ComponentUtils methods
47   *
48   * @author Kuali Rice Team (rice.collab@kuali.org)
49   */
50  public class ComponentUtilsTest {
51  
52      private String componentId;
53      private Component component;
54  
55      @Before
56      public void setup() {
57          component = new InputField();
58          componentId = "field1";
59          component.setId(componentId);
60          component.setBaseId(componentId);
61      }
62  
63  
64      // Initialization methods
65      private FieldBase initializeFieldBase() {
66          FieldBase fieldBase = new FieldBase();
67          fieldBase = (FieldBase) initializeComponentBase(fieldBase);
68          fieldBase.setShortLabel("Label");
69  
70          return fieldBase;
71      }
72  
73      private DataField initializeDataField() {
74          DataField dataField = new DataField();
75          dataField = (DataField) initializeComponentBase(dataField);
76          dataField.setAddHiddenWhenReadOnly(true);
77  
78          List<String> additionalHiddenPropertyNames = new ArrayList<String>();
79          additionalHiddenPropertyNames.add("HiddenA");
80          additionalHiddenPropertyNames.add("HiddenB");
81          additionalHiddenPropertyNames.add("HiddenC");
82          dataField.setAdditionalHiddenPropertyNames(additionalHiddenPropertyNames);
83  
84          dataField.setApplyMask(true);
85          dataField.setDefaultValue("default");
86          dataField.setDictionaryAttributeName("DictionaryName");
87          dataField.setDictionaryObjectEntry("DictionaryObjectEntry");
88          dataField.setEscapeHtmlInPropertyValue(true);
89          dataField.setForcedValue("Forced");
90          dataField.setMultiLineReadOnlyDisplay(true);
91  
92          return dataField;
93      }
94  
95      private ComponentBase initializeComponentBase(ComponentBase componentBase) {
96          List<String> additionalComponentsToRefresh = new ArrayList<String>();
97          additionalComponentsToRefresh.add("A");
98          additionalComponentsToRefresh.add("B");
99          additionalComponentsToRefresh.add("C");
100         componentBase.setAdditionalComponentsToRefresh(additionalComponentsToRefresh);
101 
102         List<String> additionalCssClasses = new ArrayList<String>();
103         additionalCssClasses.add("Class1");
104         additionalCssClasses.add("Class2");
105         additionalCssClasses.add("Class3");
106         componentBase.setAdditionalCssClasses(additionalCssClasses);
107 
108         componentBase.setAlign("right");
109 
110         List<String> cellCssClasses = new ArrayList<String>();
111         cellCssClasses.add("CellClass1");
112         cellCssClasses.add("CellClass2");
113         cellCssClasses.add("CellClass3");
114         componentBase.setCellCssClasses(cellCssClasses);
115 
116         componentBase.setCellStyle("Style1");
117         componentBase.setCellWidth("20px");
118         componentBase.setColSpan(2);
119         componentBase.setConditionalRefresh("Refresh");
120 
121         List<String> cssClasses = new ArrayList<String>();
122         cssClasses.add("CssClass1");
123         cssClasses.add("CssClass2");
124         cssClasses.add("CssClass3");
125         componentBase.setCssClasses(cssClasses);
126 
127         Map<String, String> dataAttributes = new HashMap<String, String>();
128         dataAttributes.put("One", "A");
129         dataAttributes.put("Two", "B");
130         dataAttributes.put("Three", "C");
131         componentBase.setDataAttributes(dataAttributes);
132 
133         componentBase.setFinalizeMethodToCall("methodA");
134         componentBase.setMethodToCallOnRefresh("methodB");
135         componentBase.setOnBlurScript("onblurscript");
136         componentBase.setOnChangeScript("onchangescript");
137         componentBase.setOnClickScript("onclickscript");
138         componentBase.setOnCloseScript("onclosescript");
139         componentBase.setOnDblClickScript("ondblclickscript");
140         componentBase.setOnDocumentReadyScript("ondocreadyscript");
141         componentBase.setOnFocusScript("onfocusscript");
142         componentBase.setOnKeyDownScript("onkeydownscript");
143         componentBase.setOnKeyPressScript("onkeypressscript");
144         componentBase.setOnKeyUpScript("onkeyupscript");
145         componentBase.setOnLoadScript("onloadscript");
146         componentBase.setOnMouseDownScript("onmousedownscript");
147         componentBase.setOnMouseMoveScript("onmousemovescript");
148         componentBase.setOnMouseOutScript("onmouseoutscript");
149         componentBase.setOnMouseOverScript("onmouseoverscript");
150         componentBase.setOnMouseUpScript("onmouseupscript");
151         componentBase.setOnSubmitScript("onsubmitscript");
152         componentBase.setOnUnloadScript("onunloadscript");
153         componentBase.setOrder(5);
154         componentBase.setPostRenderContent("PostRenderContent");
155         componentBase.setPreRenderContent("PreRenderContent");
156         componentBase.setProgressiveRender("ProgressiveRender");
157         componentBase.setReadOnly(false);
158         componentBase.setRefreshedByAction(false);
159         componentBase.setRefreshTimer(12);
160 
161         List<String> refreshWhenChangedPropertyNames = new ArrayList<String>();
162         refreshWhenChangedPropertyNames.add("property1");
163         refreshWhenChangedPropertyNames.add("property2");
164         refreshWhenChangedPropertyNames.add("property3");
165         componentBase.setRefreshWhenChangedPropertyNames(refreshWhenChangedPropertyNames);
166 
167         componentBase.setRenderedHtmlOutput("<output>");
168         componentBase.setRowSpan(3);
169         componentBase.setStyle("slick");
170         componentBase.setTemplate("TemplateA");
171         componentBase.setTemplateName("TemplateName");
172 
173         Map<String, String> templateOptions = new HashMap<String, String>();
174         templateOptions.put("Option1", "Value1");
175         templateOptions.put("Option1", "Value2");
176         templateOptions.put("Option1", "Value3");
177         componentBase.setTemplateOptions(templateOptions);
178 
179         componentBase.setTemplateOptionsJSString("OptionsJS");
180         componentBase.setTitle("Title");
181         componentBase.setValign("middle");
182         componentBase.setWidth("30px");
183 
184         return componentBase;
185     }
186 
187     // End of Initialization methods
188 
189     @Test
190     /**
191      * test that {@link ComponentUtils#updateIdWithSuffix} works ok
192      */
193     public void testUpdateIdWithSuffix() {
194         ComponentUtils.updateIdWithSuffix(component, null);
195         assertTrue(component.getId().equalsIgnoreCase(componentId));
196 
197         String suffix = "_field";
198         ComponentUtils.updateIdWithSuffix(component, suffix);
199         assertTrue(component.getId().equalsIgnoreCase(componentId + suffix));
200 
201     }
202 
203     @Test
204     /**
205      * test {@link ComponentUtils#copyUsingCloning} using a FieldBase object
206      */
207     public void testCopyUsingCloningWithFieldBaseSucceeds() {
208         FieldBase fieldBaseOriginal = initializeFieldBase();
209         FieldBase fieldBaseCopy = copy(fieldBaseOriginal);
210 
211         assertTrue(ComponentCopyPropertiesMatch(fieldBaseOriginal, fieldBaseCopy));
212         assertTrue(fieldBaseOriginal.getShortLabel().equals(fieldBaseCopy.getShortLabel()));
213     }
214 
215     public static <T extends Component> T copy(T component) {
216         return component.copy();
217     }
218 
219     @Test
220     /**
221      * test {@link ComponentUtils#copyUsingCloning} using a DataField object
222      */
223     public void testCopyUsingCloningWithDataFieldSucceeds() {
224         DataField dataFieldOriginal = initializeDataField();
225         DataField dataFieldCopy = copy(dataFieldOriginal);
226 
227         assertTrue(ComponentCopyPropertiesMatch(dataFieldOriginal, dataFieldCopy));
228     }
229 
230     private boolean ComponentCopyPropertiesMatch(ComponentBase originalComponent, ComponentBase copiedComponent) {
231         boolean result = true;
232 
233         List<String> missingComponentsToRefresh = originalComponent.getAdditionalComponentsToRefresh();
234         missingComponentsToRefresh.removeAll(copiedComponent.getAdditionalComponentsToRefresh());
235         if (!missingComponentsToRefresh.isEmpty()) result = false;
236 
237         List<String> missingAdditionalCssClasses = originalComponent.getAdditionalCssClasses();
238         missingAdditionalCssClasses.removeAll(copiedComponent.getAdditionalCssClasses());
239         if (!missingAdditionalCssClasses.isEmpty()) result = false;
240 
241         if (!originalComponent.getAlign().equals(copiedComponent.getAlign())) result = false;
242 
243         List<String> missingCellCssClasses = originalComponent.getCellCssClasses();
244         missingCellCssClasses.removeAll(copiedComponent.getCellCssClasses());
245         if (!missingCellCssClasses.isEmpty()) result = false;
246 
247         if (!originalComponent.getCellStyle().equals(copiedComponent.getCellStyle())) result = false;
248         if (!originalComponent.getCellWidth().equals(copiedComponent.getCellWidth())) result = false;
249         if (originalComponent.getColSpan() != copiedComponent.getColSpan()) result = false;
250         if (!originalComponent.getConditionalRefresh().equals(copiedComponent.getConditionalRefresh())) result = false;
251 
252         List<String> missingCssClasses = originalComponent.getCssClasses();
253         missingCssClasses.removeAll(copiedComponent.getCssClasses());
254         if (!missingCssClasses.isEmpty()) result = false;
255 
256         Set dataAttributes = new HashSet(originalComponent.getDataAttributes().values());
257         dataAttributes.removeAll(copiedComponent.getDataAttributes().values());
258         if (!dataAttributes.isEmpty()) result = false;
259 
260         if (!originalComponent.getFinalizeMethodToCall().equals(copiedComponent.getFinalizeMethodToCall())) result = false;
261         if (!originalComponent.getMethodToCallOnRefresh().equals(copiedComponent.getMethodToCallOnRefresh())) result = false;
262         if (!originalComponent.getOnBlurScript().equals(copiedComponent.getOnBlurScript())) result = false;
263         if (!originalComponent.getOnChangeScript().equals(copiedComponent.getOnChangeScript())) result = false;
264         if (!originalComponent.getOnClickScript().equals(copiedComponent.getOnClickScript())) result = false;
265         if (!originalComponent.getOnCloseScript().equals(copiedComponent.getOnCloseScript())) result = false;
266         if (!originalComponent.getOnDblClickScript().equals(copiedComponent.getOnDblClickScript())) result = false;
267         if (!originalComponent.getOnDocumentReadyScript().equals(copiedComponent.getOnDocumentReadyScript())) result = false;
268         if (!originalComponent.getOnFocusScript().equals(copiedComponent.getOnFocusScript())) result = false;
269         if (!originalComponent.getOnKeyDownScript().equals(copiedComponent.getOnKeyDownScript())) result = false;
270         if (!originalComponent.getOnKeyPressScript().equals(copiedComponent.getOnKeyPressScript())) result = false;
271         if (!originalComponent.getOnKeyUpScript().equals(copiedComponent.getOnKeyUpScript())) result = false;
272         if (!originalComponent.getOnLoadScript().equals(copiedComponent.getOnLoadScript())) result = false;
273         if (!originalComponent.getOnMouseDownScript().equals(copiedComponent.getOnMouseDownScript())) result = false;
274         if (!originalComponent.getOnMouseMoveScript().equals(copiedComponent.getOnMouseMoveScript())) result = false;
275         if (!originalComponent.getOnMouseOutScript().equals(copiedComponent.getOnMouseOutScript())) result = false;
276         if (!originalComponent.getOnMouseOverScript().equals(copiedComponent.getOnMouseOverScript())) result = false;
277         if (!originalComponent.getOnMouseUpScript().equals(copiedComponent.getOnMouseUpScript())) result = false;
278         if (!originalComponent.getOnSubmitScript().equals(copiedComponent.getOnSubmitScript())) result = false;
279         if (!originalComponent.getOnUnloadScript().equals(copiedComponent.getOnUnloadScript())) result = false;
280         if (originalComponent.getOrder() != copiedComponent.getOrder()) result = false;
281         if (!originalComponent.getPostRenderContent().equals(copiedComponent.getPostRenderContent())) result = false;
282         if (!originalComponent.getPreRenderContent().equals(copiedComponent.getPreRenderContent())) result = false;
283         if (!originalComponent.getProgressiveRender().equals(copiedComponent.getProgressiveRender())) result = false;
284         if (originalComponent.getRequired() != copiedComponent.getRequired()) result = false;
285         if (originalComponent.getRefreshTimer() != copiedComponent.getRefreshTimer()) result = false;
286 
287         List<String> missingRefreshWhenChangedPropertyNames = originalComponent.getRefreshWhenChangedPropertyNames();
288         missingRefreshWhenChangedPropertyNames.removeAll(copiedComponent.getRefreshWhenChangedPropertyNames());
289         if (!missingRefreshWhenChangedPropertyNames.isEmpty()) result = false;
290 
291         if (!originalComponent.getRenderedHtmlOutput().equals(copiedComponent.getRenderedHtmlOutput())) result = false;
292         if (originalComponent.getRowSpan() != copiedComponent.getRowSpan()) result = false;
293         if (!originalComponent.getStyle().equals(copiedComponent.getStyle())) result = false;
294         if (!originalComponent.getTemplate().equals(copiedComponent.getTemplate())) result = false;
295         if (!originalComponent.getTemplateName().equals(copiedComponent.getTemplateName())) result = false;
296 
297         Set templateOptions = new HashSet(originalComponent.getTemplateOptions().values());
298         templateOptions.removeAll(copiedComponent.getTemplateOptions().values());
299         if (!templateOptions.isEmpty()) result = false;
300 
301         if (!originalComponent.getTemplateOptionsJSString().equals(copiedComponent.getTemplateOptionsJSString())) result = false;
302         if (!originalComponent.getTitle().equals(copiedComponent.getTitle())) result = false;
303         if (!originalComponent.getValign().equals(copiedComponent.getValign())) result = false;
304         if (!originalComponent.getWidth().equals(copiedComponent.getWidth())) result = false;
305 
306         return result;
307     }
308 
309     @Ignore // Ignored for now, but this is a proof of concept for using reflection to test copying
310     @Test
311     /**
312      * test {@link ComponentUtils#copyUsingCloning} using a DataField object
313      */
314     public void testCopyUsingCloningWithDataTableSucceeds() {
315         CheckboxControl dataTableOriginal = new CheckboxControl();
316 
317         initializeClass(dataTableOriginal);
318 
319         CheckboxControl dataTableCopy = copy(dataTableOriginal);
320 
321         assertTrue(propertiesMatch(dataTableOriginal, dataTableCopy));
322     }
323 
324     private void initializeClass(Object originalObject) {
325         Class originalClass = originalObject.getClass();
326         long index = 0L;
327 
328         for (Field field : originalClass.getDeclaredFields()) {
329             if (field.isAnnotationPresent(ReferenceCopy.class)) continue;
330 
331             try {
332                 if (field.getType().equals(String.class)) {
333                     field.setAccessible(true);
334                     field.set(originalObject, "Test" + index);
335                 }
336 
337                 if (field.getType().equals(long.class)) {
338                     field.setAccessible(true);
339                     field.setLong(originalObject, index);
340                 }
341 
342                 if (field.getType().equals(int.class)) {
343                     field.setAccessible(true);
344                     field.setInt(originalObject, (int) index);
345                 }
346 
347                 if (field.getType().equals(List.class)) {
348                     field.setAccessible(true);
349                     ParameterizedType myListType = ((ParameterizedType) field.getGenericType());
350                     //myListType.getActualTypeArguments()[0].name;    // string value that looks like this: interface org.kuali.rice.krad.uif.component.Component
351                     int something = 2;
352                     //Class listClass = Class.forName(myListType.getActualTypeArguments()[0]);
353                     Object[] objects = new Object[1];
354                     objects[0] = new FieldBase();
355                     List<?> fieldList = Arrays.asList((Object[]) objects);
356                     field.set(originalObject, fieldList);
357                     List<?> retrievedList = (List<?>)field.get(originalObject);
358                     int somethingElse = 3;
359 
360                     //ArrayList<?> arrayList = new ArrayList<?>();
361 
362                 }
363             } catch (IllegalAccessException e) {
364                 // do nothing
365             }
366 
367             ++index;
368         }
369     }
370 
371     private boolean propertiesMatch(Object originalObject, Object copiedObject) {
372         Class originalClass = originalObject.getClass();
373         Class copiedClass = copiedObject.getClass();
374 
375         for (Field field : originalClass.getDeclaredFields()) {
376             if (field.isAnnotationPresent(ReferenceCopy.class)) continue;
377 
378             if (field.getType().equals(String.class)) {
379                 boolean propertiesMatch = stringPropertiesMatch(originalObject, copiedObject, copiedClass, field);
380                 if (!propertiesMatch) return false;
381             }
382 
383             if (field.getType().equals(long.class)) {
384                 boolean propertiesMatch = longPropertiesMatch(originalObject, copiedObject, copiedClass, field);
385                 if (!propertiesMatch) return false;
386             }
387 
388             if (field.getType().equals(int.class)) {
389                 boolean propertiesMatch = intPropertiesMatch(originalObject, copiedObject, copiedClass, field);
390                 if (!propertiesMatch) return false;
391             }
392         }
393 
394         return true;
395     }
396 
397     private boolean intPropertiesMatch(Object originalObject, Object copiedObject, Class copiedClass, Field field) {
398         try {
399             field.setAccessible(true);
400             int oritinalInt = field.getInt(originalObject);
401             Field copiedClassField = copiedClass.getDeclaredField(field.getName());
402             copiedClassField.setAccessible(true);
403             int copiedInt = copiedClassField.getInt(copiedObject);
404 
405             return oritinalInt == copiedInt;
406         }
407         catch (IllegalAccessException e) {
408             return false;
409         } catch (NoSuchFieldException e) {
410             return false;
411         }
412     }
413 
414     private boolean longPropertiesMatch(Object originalObject, Object copiedObject, Class copiedClass, Field field) {
415         try {
416             field.setAccessible(true);
417             Long originalLong = field.getLong(originalObject);
418             Field copiedClassField = copiedClass.getDeclaredField(field.getName());
419             copiedClassField.setAccessible(true);
420             Long copiedLong = copiedClassField.getLong(copiedObject);
421 
422             return originalLong.equals(copiedLong);
423         }
424         catch (IllegalAccessException e) {
425             return false;
426         } catch (NoSuchFieldException e) {
427             return false;
428         }
429     }
430 
431     private boolean stringPropertiesMatch(Object originalObject, Object copiedObject, Class copiedClass, Field field) {
432         try {
433             field.setAccessible(true);
434             String originalString = (String) field.get(originalObject);
435             String copiedString = new String();
436             Field copiedClassField = copiedClass.getDeclaredField(field.getName());
437             copiedClassField.setAccessible(true);
438             copiedString = (String) copiedClassField.get(copiedObject);
439 
440             return originalString.equals(copiedString);
441         } catch (IllegalAccessException e) {
442             return false;
443         }
444         catch (NoSuchFieldException e) {
445             return false;
446         }
447     }
448 }