1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.beanmerger;
35
36 import java.lang.reflect.Modifier;
37 import java.net.URL;
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.List;
41 import java.util.Map;
42
43 import org.apache.commons.collections4.CollectionUtils;
44 import org.apache.commons.collections4.functors.NotNullPredicate;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52 public abstract class BeanMergerBase implements BeanMerger {
53
54 protected Logger log = LoggerFactory.getLogger(this.getClass());
55
56 @Override
57 public Object merge(List sources) {
58 CollectionUtils.filter(sources, NotNullPredicate.INSTANCE);
59 if (sources.isEmpty()) {
60 return null;
61 }
62
63 if (sources.size() == 1 || isSimpleType(sources.get(0).getClass()) || !isMergeable(sources.get(0).getClass())) {
64 return sources.get(0);
65 }
66
67 if (sources.get(0) instanceof Collection) {
68 return mergeCollections(sources);
69 }
70
71 if (sources.get(0) instanceof Map) {
72 return mergeMaps(sources);
73 }
74
75 return mergeBean(sources);
76 }
77
78 protected abstract Object mergeBean(List sources);
79
80 protected Map mergeMaps(List<Map> sources) {
81 try {
82 Map mergedMap = this.instantiateOneOf(sources);
83 for (Map map : sources) {
84 for (Object key : map.keySet()) {
85 List values = new ArrayList();
86 for (Map map2 : sources) {
87 if (map2.containsKey(key)) {
88 values.add(map2.get(key));
89 }
90 }
91 mergedMap.put(key, merge(values));
92 }
93 }
94 return mergedMap;
95 } catch (Exception e) {
96 log.error(e.getMessage(), e);
97 return sources.get(0);
98 }
99 }
100
101 protected Collection mergeCollections(List<Collection> sources) {
102 try {
103 Collection mergedCol = this.instantiateOneOf(sources);
104 for (Collection col : sources) {
105 mergedCol.addAll(col);
106 }
107 return mergedCol;
108 } catch (Exception e) {
109 log.error(e.getMessage(), e);
110 return sources.get(0);
111 }
112 }
113
114
115
116
117
118
119
120
121
122 protected boolean isSimpleType(Class type) {
123 return type.isPrimitive() ||
124 type == Object.class ||
125 type == Boolean.class ||
126 type == Byte.class ||
127 type == Character.class ||
128 type == Short.class ||
129 type == Integer.class ||
130 type == Long.class ||
131 type == Float.class ||
132 type == Double.class ||
133 type == Void.class ||
134
135 type == String.class ||
136 type == Class.class ||
137 type == URL.class;
138 }
139
140
141
142
143
144
145
146
147 protected boolean isMergeable(Class type) {
148 if (Modifier.isFinal(type.getModifiers())) {
149 return false;
150 }
151 if (Modifier.isInterface(type.getModifiers())) {
152 return Map.class.isAssignableFrom(type) || Collection.class.isAssignableFrom(type);
153 }
154 return true;
155 }
156
157 private <T>T instantiateOneOf(List<T> sources) throws IllegalAccessException, InstantiationException {
158 for (T object : sources) {
159 try {
160 return (T) object.getClass().newInstance();
161 } catch (ReflectiveOperationException e) {
162 if (object == sources.get(sources.size() - 1)) {
163 throw e;
164 }
165 }
166 }
167 return null;
168 }
169
170 }