View Javadoc
1   /**
2    * Copyright 2005-2015 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.util.documentserializer;
17  
18  import org.kuali.rice.krad.bo.BusinessObject;
19  import org.kuali.rice.krad.document.Document;
20  import org.kuali.rice.krad.util.documentserializer.PropertySerializabilityMetadata.PropertySerializability;
21  
22  import java.util.Collection;
23  import java.util.Map;
24  
25  /**
26   * This abstract implementation provides a default implementation of {@link #determinePropertyType(Object)}, which should suffice for most
27   * use cases.
28   *
29   */
30  public abstract class PropertySerializabilityEvaluatorBase implements PropertySerializabilityEvaluator {
31  
32      protected PropertySerializerTrie serializableProperties;
33  
34      @Override
35  	public void initializeEvaluatorForDocument(Document document){
36  
37  	}
38  
39      @Override
40  	public void initializeEvaluatorForDataObject(Object businessObject){
41  
42  	}
43  
44      /**
45       * @see org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator#determinePropertyType(java.lang.Object)
46       */
47      @Override
48      public PropertyType determinePropertyType(Object propertyValue) {
49          if (propertyValue == null) {
50              return PropertyType.PRIMITIVE;
51          }
52          if (propertyValue instanceof BusinessObject) {
53              return PropertyType.BUSINESS_OBJECT;
54          }
55          if (propertyValue instanceof Collection) {
56              return PropertyType.COLLECTION;
57          }
58          if (propertyValue instanceof Map) {
59              return PropertyType.MAP;
60          }
61          return PropertyType.PRIMITIVE;
62      }
63  
64      /**
65       * Returns whether a child property of a given containing object should be serialized, based on the metadata provided in the data dictionary.
66       *
67       * @see org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator#isPropertySerializable(SerializationState, Object, String, Object)
68       */
69      @Override
70      public boolean isPropertySerializable(SerializationState state, Object containingObject, String childPropertyName, Object childPropertyValue) {
71          boolean allPropertiesMatched = true;
72  
73          PropertySerializabilityMetadata metadata = serializableProperties.getRootPropertySerializibilityMetadata();
74          int i = 0;
75          for (; i < state.numPropertyElements(); i++) {
76              String nextPropertyName = state.getElementName(i);
77              PropertySerializabilityMetadata nextMetadata = metadata.getSerializableChildProperty(nextPropertyName);
78  
79              if (nextMetadata == null) {
80                  allPropertiesMatched = false;
81                  break;
82              }
83              else {
84                  // we've found the child... continue searching deeper
85                  metadata = nextMetadata;
86              }
87          }
88  
89          if (allPropertiesMatched) {
90              // complete match, so we determine if the child property is serializable
91              return evaluateCompleteMatch(state, containingObject, metadata, childPropertyName, childPropertyValue);
92          }
93          else {
94              // we have a partial match, so we have a different algorithm to determine serializibility
95              // partial matches can occur for primitives that contains nested primitives.  For example, if we have a member field named
96              // "amount" of type KualiDecimal, then the XML will have to look something like <amount><value>100.00</value></amount>.
97              // It is likely that "value" isn't specified in the serializability path, so we need to make inferences about whether "value" is 
98              // serializable
99              return evaluatePartialMatch(state, i, containingObject, metadata, childPropertyName, childPropertyValue);
100         }
101     }
102 
103     /**
104      * Evaluates whether a property is serializable when all properties in the serialization state have been matched up with the properties
105      * defined in the data dictionary.
106      *
107      * @param state
108      * @param containingObject
109      * @param metadata
110      * @param childPropertyName
111      * @param childPropertyValue
112      * @return whether the child property is serializable
113      */
114     protected boolean evaluateCompleteMatch(SerializationState state, Object containingObject, PropertySerializabilityMetadata metadata, String childPropertyName, Object childPropertyValue) {
115         if (metadata.getPropertySerializability().equals(PropertySerializability.SERIALIZE_OBJECT_AND_ALL_PRIMITIVES)) {
116             if (isPrimitiveObject(childPropertyValue)) {
117                 return true;
118             }
119         }
120         return metadata.getSerializableChildProperty(childPropertyName) != null;
121     }
122 
123     /**
124      * Evaluates whether a property is serializable when only some of the properties in the serialization state have been matched up with the
125      * serializable properties specified in the data dictionary.  This often occurs when we determine whether to serialize a primitive of a serialized primitive
126      *
127      * @param state
128      * @param lastMatchedStateIndex the index of the state parameter that represents the last matched property
129      * @param containingObject the object containing the child property
130      * @param metadata metadata of the last matched property
131      * @param childPropertyName the name of the child property that we are going to determine whether it is serializable
132      * @param childPropertyValue the value of the child property that we are going to determine whether it is serializable
133      * @return whether the child property is serializable
134      */
135     protected boolean evaluatePartialMatch(SerializationState state, int lastMatchedStateIndex, Object containingObject, PropertySerializabilityMetadata metadata, String childPropertyName, Object childPropertyValue) {
136 
137         if (metadata.getPropertySerializability().equals(PropertySerializability.SERIALIZE_OBJECT_AND_ALL_PRIMITIVES)) {
138             return isPrimitiveObject(childPropertyValue);
139         }
140         return false;
141     }
142 
143     /**
144      * Whether the object represents a primitive
145      *
146      * @param object
147      * @return
148      */
149     protected boolean isPrimitiveObject(Object object) {
150         return PropertyType.PRIMITIVE.equals(determinePropertyType(object));
151     }
152 
153 }