1 package org.cateproject.controller.flow.action.upload;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.apache.log4j.Logger;
9 import org.springframework.beans.BeanWrapperImpl;
10 import org.springframework.beans.InvalidPropertyException;
11 import org.springframework.beans.NullValueInNestedPathException;
12 import org.springframework.core.convert.ConversionService;
13 import org.springframework.util.ReflectionUtils;
14
15 import eu.etaxonomy.cdm.api.service.ITermService;
16 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
17 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
18 import eu.etaxonomy.cdm.persistence.query.OrderHint;
19 import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;
20
21 public class AbstractMatrixHeader<T extends IdentifiableEntity> implements Serializable, Comparable<AbstractMatrixHeader<T>> {
22
23
24
25 private static final long serialVersionUID = 1L;
26
27 protected static Logger logger = Logger.getLogger(AbstractMatrixHeader.class);
28
29 private int index;
30 private String fullPath;
31 private String path;
32
33 private String label;
34 private AbstractMatrixHeaderType type;
35 private Class<T> clazz;
36 private List<Class> classes;
37 private List<HeaderPath> paths = new ArrayList<HeaderPath>();
38 private List<DefinedTermBase> terms = new ArrayList<DefinedTermBase>();
39
40 private boolean set = false;
41
42 public AbstractMatrixHeader(String path, int index, Class<T> clazz, Map<Class,List<Class>> classes, ITermService termService) {;
43 this.label = path;
44 this.index = index;
45 this.clazz = clazz;
46
47 this.fullPath = path;
48
49 if(path.endsWith(".class")) {
50 this.path = path.substring(0, path.lastIndexOf(".class"));
51 this.type = AbstractMatrixHeaderType.CLASS;
52 } else if(path.equals("class")) {
53 this.path = "";
54 this.type = AbstractMatrixHeaderType.ROOT_CLASS;
55 }else {
56 this.type = AbstractMatrixHeaderType.PROPERTY;
57 this.path = path;
58 }
59 logger.info("Constructing header for " + path + " " + clazz + " " + classes.get(clazz));
60 HeaderPath p = new HeaderPath(clazz, classes.get(clazz), path);
61 this.paths.add(p);
62 while(!p.isTerminating()) {
63 if(classes.containsKey(p.getPropertyType())) {
64 p = new HeaderPath(p.getPropertyType(),classes.get(p.getPropertyType()),p.getRemainingPath());
65 } else {
66 p = new HeaderPath(p.getPropertyType(),p.getRemainingPath());
67 }
68 this.paths.add(p);
69 }
70
71 Class terminalPropertyType = this.paths.get(this.paths.size() - 1).getPropertyType();
72
73 if(terminalPropertyType != null && DefinedTermBase.class.isAssignableFrom(terminalPropertyType)) {
74 List<OrderHint> orderHints = new ArrayList<OrderHint>();
75 orderHints.add(new OrderHint("titleCache",SortOrder.ASCENDING));
76 this.terms = termService.list(terminalPropertyType, null, null, orderHints, null);
77 }
78
79 }
80
81 public boolean isNested() {
82 return this.paths.get(0).isTerminating();
83 }
84
85 public HeaderPath[] getPaths() {
86 return this.paths.toArray(new HeaderPath[this.paths.size()]);
87 }
88
89
90 public MatrixHeader<T> getHeaderForObject(T o, ConversionService conversionService) {
91 if(this.isApplicable(o,conversionService)) {
92 if(this.getType().equals(AbstractMatrixHeaderType.ROOT_CLASS)) {
93 return new RootClassMatrixHeader<T>(clazz);
94 } else if(this.getType().equals(AbstractMatrixHeaderType.CLASS)) {
95 return new ClassMatrixHeader<T>(this.path,this.paths,o);
96 } else {
97 return new PropertyMatrixHeader<T>(this.path,this.paths,o,terms);
98 }
99 } else {
100 return null;
101 }
102 }
103
104 public boolean isApplicable(Object o, ConversionService conversionService) {
105 if(this.type.equals(AbstractMatrixHeaderType.ROOT_CLASS)) {
106 return true;
107 } else if(this.type.equals(AbstractMatrixHeaderType.CLASS) && this.paths.get(0).isCollection()) {
108 if(ReflectionUtils.findField(o.getClass(), this.paths.get(0).getProperty()) != null) {
109 return true;
110 } else {
111 return false;
112 }
113 } else {
114 BeanWrapperImpl beanWrapperImpl = new BeanWrapperImpl(o);
115 beanWrapperImpl.setAutoGrowNestedPaths(true);
116 beanWrapperImpl.setConversionService(conversionService);
117 try {
118 beanWrapperImpl.getPropertyDescriptor(this.path);
119 return true;
120 } catch(IllegalArgumentException iae) {
121 logger.info(iae.getMessage());
122 return false;
123 } catch(NullValueInNestedPathException nvinpe) {
124 logger.info(nvinpe.getMessage());
125 return false;
126 } catch(InvalidPropertyException ipe) {
127 logger.info(ipe.getMessage());
128 return false;
129 }
130 }
131 }
132
133 public boolean isClassType() {
134 return type.equals(AbstractMatrixHeaderType.CLASS);
135 }
136
137 public boolean isObjectType() {
138 return type.equals(AbstractMatrixHeaderType.PROPERTY);
139 }
140
141 public int getIndex() {
142 return index;
143 }
144
145 public String getLabel() {
146 return this.label;
147 }
148
149 public String getPath(String prefix) {
150 if(path == "") {
151 return prefix;
152 }
153 return prefix + "." + path;
154 }
155
156 protected String getPath() {
157 return path;
158 }
159
160 public int compareTo(AbstractMatrixHeader o) {
161 if(this.path.contains(".")) {
162 if(!o.getPath().contains(".")) {
163 return -1;
164 } else{
165 String path1 = this.path.substring(0,this.path.lastIndexOf("."));
166 String path2 = o.getPath().substring(0, o.getPath().lastIndexOf("."));
167 if(path1.equals(path2)) {
168 String property1 = this.path.substring(this.path.lastIndexOf(".") + 1);
169 String property2 = o.getPath().substring(o.getPath().lastIndexOf(".") + 1);
170 if(property1.equals("class") && property2.contains("class")) {
171 return 0;
172 } else if(property1.equals("class")) {
173 return 1;
174 } else if(property2.equals("class")) {
175 return -1;
176 } else {
177 return property1.compareTo(property2);
178 }
179 } else{
180 return path1.compareTo(path2);
181 }
182 }
183 } else {
184 if(o.getPath().contains(".")) {
185 return 1;
186 } else {
187 if(this.path.equals("class") && o.getPath().contains("class")) {
188 return 0;
189 } else if(this.path.equals("class")) {
190 return 1;
191 } else if(o.getPath().equals("class")) {
192 return -1;
193 } else {
194 return this.path.compareTo(o.getPath());
195 }
196 }
197 }
198 }
199
200 public AbstractMatrixHeaderType getType() {
201 return type;
202 }
203
204 public List<DefinedTermBase> getTerms() {
205 return terms;
206 }
207
208 public Class<T> getClazz() {
209 return clazz;
210 }
211
212 public Class getFieldType() {
213 return this.paths.get(this.paths.size() - 1).getPropertyType();
214 }
215
216 public boolean isSet() {
217 if(this.paths.size() == 1) {
218 return false;
219 } else {
220 return this.paths.get(this.paths.size() - 2).isSet();
221 }
222 }
223
224 public boolean isMap() {
225 if(this.paths.size() == 1) {
226 return false;
227 } else {
228 return this.paths.get(this.paths.size() - 2).isMap();
229 }
230 }
231 }