2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.remote
.json
.processor
.bean
;
11 import java
.beans
.PropertyDescriptor
;
12 import java
.lang
.reflect
.InvocationTargetException
;
13 import java
.util
.Collection
;
14 import java
.util
.HashSet
;
15 import java
.util
.List
;
19 import org
.apache
.commons
.beanutils
.PropertyUtils
;
20 import org
.apache
.logging
.log4j
.LogManager
;import org
.apache
.logging
.log4j
.Logger
;
21 import org
.hibernate
.Hibernate
;
23 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
24 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.AbstractBeanInitializer
;
25 import net
.sf
.json
.JSONException
;
26 import net
.sf
.json
.JSONObject
;
27 import net
.sf
.json
.JsonConfig
;
28 import net
.sf
.json
.processors
.JsonBeanProcessor
;
29 import net
.sf
.json
.processors
.JsonValueProcessor
;
30 import net
.sf
.json
.processors
.JsonVerifier
;
31 import net
.sf
.json
.util
.PropertyFilter
;
34 * @author a.kohlbecker
37 public abstract class AbstractBeanProcessor
<T
extends Object
> implements JsonBeanProcessor
{
39 public static final Logger logger
= LogManager
.getLogger(AbstractBeanProcessor
.class);
41 private Set
<String
> excludes
= new HashSet
<>();
43 private Set
<String
> mergedExcludes
= null;
45 public Set
<String
> getExcludes() {
50 * This method allows supplying a List of property names to be ignored
51 * during the serialization to JSON. The <code>excludes</code> will be
52 * merged with the property names configured by subclasses which override
53 * {@link {@link #getIgnorePropNames()}.
57 public void setExcludes(Set
<String
> excludes
) {
58 this.excludes
= excludes
;
62 * Implementations of this abstract class may override this method in order
63 * to supply a List of property names to be ignored in
64 * {@link #processBean(Object, JsonConfig)}. This feature generally is used
65 * when {@link #processBeanSecondStep(CdmBase, JSONObject, JsonConfig)} is
66 * implemented. such that this method is responsible of serializing this
69 * @return a List of property names.
71 public abstract List
<String
> getIgnorePropNames();
74 * merges and returns {@link {@link #getIgnorePropNames()} with
79 protected Set
<String
> getMergedExcludes(){
80 if(mergedExcludes
== null) {
81 mergedExcludes
= new HashSet
<>(excludes
);
82 if(getIgnorePropNames() != null){
83 mergedExcludes
.addAll(getIgnorePropNames());
87 return mergedExcludes
;
90 protected void addJsonElement(JSONObject json
, JsonConfig jsonConfig
, String fieldName
, Object fieldObject
) {
91 if(Hibernate
.isInitialized(fieldObject
)){
92 json
.element(fieldName
, fieldObject
, jsonConfig
);
97 public final JSONObject
processBean(Object bean
, JsonConfig jsonConfig
) {
99 if(logger
.isDebugEnabled()){
100 logger
.debug("processing " + bean
.getClass());
103 JSONObject json
= new JSONObject();
104 Collection
<?
> exclusions
= jsonConfig
.getMergedExcludes( bean
.getClass() );
105 Set
<PropertyDescriptor
> props
= AbstractBeanInitializer
.getProperties(bean
, null);
106 PropertyFilter jsonPropertyFilter
= jsonConfig
.getJsonPropertyFilter();
107 for(PropertyDescriptor prop
: props
){
108 String key
= prop
.getName();
109 if(getMergedExcludes().contains(key
) || exclusions
.contains(key
)){
110 if(logger
.isDebugEnabled()){
111 logger
.debug("skipping excluded property " + key
);
117 // ------ reusing snippet from JSONOnbject._fromBean()
118 Class
<?
> type
= prop
.getPropertyType();
119 Object value
= PropertyUtils
.getProperty( bean
, key
);
121 if( jsonPropertyFilter
!= null && jsonPropertyFilter
.apply( bean
, key
, value
) ){
124 JsonValueProcessor jsonValueProcessor
= jsonConfig
.findJsonValueProcessor(bean
.getClass(), type
, key
);
125 if( jsonValueProcessor
!= null ){
126 value
= jsonValueProcessor
.processObjectValue( key
, value
, jsonConfig
);
127 if( !JsonVerifier
.isValidJsonValue( value
) ){
128 throw new JSONException( "Value is not a valid JSON value. " + value
);
131 // ----- END of snipped
132 if(logger
.isDebugEnabled()){
133 logger
.debug("processing " + key
+ " of " + bean
.getClass());
135 if(CdmBase
.class.isAssignableFrom(type
)){
136 json
.element(key
, value
, jsonConfig
);
137 } else if(Collection
.class.isAssignableFrom(type
) || Map
.class.isAssignableFrom(type
)){
138 json
.element(key
, value
, jsonConfig
);
139 } else if(Object
.class.isAssignableFrom(type
)){
140 json
.element(key
, value
, jsonConfig
);
142 json
.element(key
, value
);
145 } catch (IllegalAccessException
| InvocationTargetException
| NoSuchMethodException e
) {
146 logger
.error(e
.getMessage(), e
);
150 json
= processBeanSecondStep((T
) bean
, json
, jsonConfig
);
156 * This method is called at the end of {@link #processBean(Object, JsonConfig)} just before the JSONObject is returned.
157 * By overriding this method it is possible to do further processing.
159 * <b>See also {@link #getIgnorePropNames()}!</b>
161 public abstract JSONObject
processBeanSecondStep(T bean
, JSONObject json
, JsonConfig jsonConfig
) ;