3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.remote
.json
.processor
.bean
;
12 import java
.beans
.PropertyDescriptor
;
13 import java
.lang
.reflect
.InvocationTargetException
;
14 import java
.util
.Collection
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
20 import net
.sf
.json
.JSONException
;
21 import net
.sf
.json
.JSONObject
;
22 import net
.sf
.json
.JsonConfig
;
23 import net
.sf
.json
.processors
.JsonBeanProcessor
;
24 import net
.sf
.json
.processors
.JsonValueProcessor
;
25 import net
.sf
.json
.processors
.JsonVerifier
;
26 import net
.sf
.json
.util
.PropertyFilter
;
28 import org
.apache
.commons
.beanutils
.PropertyUtils
;
29 import org
.apache
.log4j
.Logger
;
30 import org
.hibernate
.Hibernate
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
33 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
34 import eu
.etaxonomy
.cdm
.persistence
.dao
.AbstractBeanInitializer
;
37 * @author a.kohlbecker
41 public abstract class AbstractBeanProcessor
<T
extends Object
> implements JsonBeanProcessor
{
43 public static final Logger logger
= Logger
.getLogger(AbstractBeanProcessor
.class);
45 private Set
<String
> excludes
= new HashSet
<String
>();
47 public Set
<String
> getExcludes() {
52 * This method allows supplying a List of property names to be ignored
53 * during the serialization to JSON. The <code>excludes</code> will be
54 * merged with the property names configured by subclasses which override
55 * {@link {@link #getIgnorePropNames()}.
59 public void setExcludes(Set
<String
> excludes
) {
60 this.excludes
= excludes
;
64 * Implementations of this abstract class may override this method in order
65 * to supply a List of property names to be ignored in
66 * {@link #processBean(Object, JsonConfig)}. This feature generally is used
67 * when {@link #processBeanSecondStep(CdmBase, JSONObject, JsonConfig)} is
68 * implemented. such that this method is responsible of serializing this
71 * @return a List of property names.
73 public abstract List
<String
> getIgnorePropNames();
76 * merges and returns {@link {@link #getIgnorePropNames()} with
81 protected Set
<String
> getMergedExcludes(){
82 Set
<String
> mergedExcludes
= new HashSet
<String
>(excludes
);
83 if(getIgnorePropNames() != null){
84 mergedExcludes
.addAll(getIgnorePropNames());
86 return mergedExcludes
;
96 protected void addJsonElement(JSONObject json
, JsonConfig jsonConfig
, String fieldName
, Object fieldObject
) {
97 if(Hibernate
.isInitialized(fieldObject
)){
98 json
.element(fieldName
, fieldObject
, jsonConfig
);
104 * @see net.sf.json.processors.JsonBeanProcessor#processBean(java.lang.Object, net.sf.json.JsonConfig)
106 public final JSONObject
processBean(Object bean
, JsonConfig jsonConfig
) {
108 if(logger
.isDebugEnabled()){
109 logger
.debug("processing " + bean
.getClass());
112 JSONObject json
= new JSONObject();
113 Collection exclusions
= jsonConfig
.getMergedExcludes( bean
.getClass() );
114 Set
<Class
> typeRestrictions
= new HashSet
<Class
>();
115 typeRestrictions
.add(CdmBase
.class);
116 Set
<PropertyDescriptor
> props
= AbstractBeanInitializer
.getProperties(bean
, null);
117 PropertyFilter jsonPropertyFilter
= jsonConfig
.getJsonPropertyFilter();
118 for(PropertyDescriptor prop
: props
){
119 String key
= prop
.getName();
120 if(getMergedExcludes().contains(key
) || exclusions
.contains(key
)){
121 if(logger
.isDebugEnabled()){
122 logger
.debug("skipping excluded property " + key
);
128 // ------ reusing snippet from JSONOnbject._fromBean()
129 Class type
= prop
.getPropertyType();
130 Object value
= PropertyUtils
.getProperty( bean
, key
);
132 if( jsonPropertyFilter
!= null && jsonPropertyFilter
.apply( bean
, key
, value
) ){
135 JsonValueProcessor jsonValueProcessor
= jsonConfig
.findJsonValueProcessor(bean
.getClass(), type
, key
);
136 if( jsonValueProcessor
!= null ){
137 value
= jsonValueProcessor
.processObjectValue( key
, value
, jsonConfig
);
138 if( !JsonVerifier
.isValidJsonValue( value
) ){
139 throw new JSONException( "Value is not a valid JSON value. " + value
);
142 // ----- END of snipped
143 if(logger
.isDebugEnabled()){
144 logger
.debug("processing " + key
+ " of " + bean
.getClass());
146 if(CdmBase
.class.isAssignableFrom(type
)){
147 json
.element(key
, value
, jsonConfig
);
148 } else if(Collection
.class.isAssignableFrom(type
) || Map
.class.isAssignableFrom(type
)){
149 json
.element(key
, value
, jsonConfig
);
150 } else if(Object
.class.isAssignableFrom(type
)){
151 json
.element(key
, value
, jsonConfig
);
153 json
.element(key
, value
);
156 } catch (IllegalAccessException e
) {
157 logger
.error(e
.getMessage(), e
);
158 } catch (InvocationTargetException e
) {
159 logger
.error(e
.getMessage(), e
);
160 } catch (NoSuchMethodException e
) {
161 logger
.error(e
.getMessage(), e
);
165 json
= processBeanSecondStep((T
) bean
, json
, jsonConfig
);
171 * This method is called ate the end of {@link #processBean(Object, JsonConfig)} just before the JSONObject is returned.
172 * By overriding this method it is possible to to further processing.
174 * <b>See also {@link #getIgnorePropNames()}!</b>
181 public abstract JSONObject
processBeanSecondStep(T bean
, JSONObject json
, JsonConfig jsonConfig
) ;