minor
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / CommonServiceImpl.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
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.
9 */
10
11 package eu.etaxonomy.cdm.api.service;
12
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.apache.log4j.Logger;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Service;
23 import org.springframework.transaction.annotation.Propagation;
24 import org.springframework.transaction.annotation.Transactional;
25
26 import eu.etaxonomy.cdm.api.service.pager.Pager;
27 import eu.etaxonomy.cdm.database.DatabaseSchemaMismatchException;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.common.CdmMetaData;
30 import eu.etaxonomy.cdm.model.common.ISourceable;
31 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
32 import eu.etaxonomy.cdm.model.common.OriginalSourceBase;
33 import eu.etaxonomy.cdm.model.common.CdmMetaData.MetaDataPropertyName;
34 import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
35 import eu.etaxonomy.cdm.persistence.dao.common.IOriginalSourceDao;
36 import eu.etaxonomy.cdm.persistence.query.OrderHint;
37 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
38 import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
39 import eu.etaxonomy.cdm.strategy.match.IMatchable;
40 import eu.etaxonomy.cdm.strategy.match.MatchException;
41 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
42 import eu.etaxonomy.cdm.strategy.merge.IMergable;
43 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
44 import eu.etaxonomy.cdm.strategy.merge.MergeException;
45
46
47 @Service
48 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
49 public class CommonServiceImpl extends ServiceBase<OriginalSourceBase,IOriginalSourceDao> implements ICommonService {
50 private static final Logger logger = Logger.getLogger(CommonServiceImpl.class);
51
52 @Autowired
53 IOriginalSourceDao originalSourceDao;
54
55 @Autowired
56 ICdmGenericDao genericDao;
57
58
59 @Autowired
60 protected void setDao(IOriginalSourceDao dao) {
61 this.dao = dao;
62 }
63
64 /* (non-Javadoc)
65 * @see eu.etaxonomy.cdm.api.service.ICommonService#getSourcedObjectById(java.lang.String, java.lang.String)
66 */
67 public ISourceable getSourcedObjectByIdInSource(Class clazz, String idInSource, String idNamespace) {
68 ISourceable result = null;
69 // List<OriginalSource> originalSource = originalSourceDao.findOriginalSourceByIdInSource(idInSource, idNamespace);
70 // if (! originalSource.isEmpty()){
71 // result = originalSource.get(0).getSourcedObj();
72 // }
73 List<IdentifiableEntity> list = originalSourceDao.findOriginalSourceByIdInSource(clazz, idInSource, idNamespace);
74 if (! list.isEmpty()){
75 result = list.get(0);
76 }
77 return result;
78 }
79
80
81 /* (non-Javadoc)
82 * @see eu.etaxonomy.cdm.api.service.ICommonService#getReferencingObjects(eu.etaxonomy.cdm.model.common.CdmBase)
83 */
84 public Set<CdmBase> getReferencingObjects(CdmBase referencedCdmBase){
85 return this.genericDao.getReferencingObjects(referencedCdmBase);
86 }
87 // try {
88 // Set<Class<? extends CdmBase>> allCdmClasses = genericDao.getAllCdmClasses(false); //findAllCdmClasses();
89 //
90 // referencedCdmBase = (CdmBase)HibernateProxyHelper.deproxy(referencedCdmBase);
91 // Class referencedClass = referencedCdmBase.getClass();
92 // Set<CdmBase> result = new HashSet<CdmBase>();
93 // logger.debug("Referenced Class: " + referencedClass.getName());
94 //
95 // for (Class<? extends CdmBase> cdmClass : allCdmClasses){
96 // Set<Field> fields = getFields(cdmClass);
97 // for (Field field: fields){
98 // Class<?> type = field.getType();
99 // //class
100 // if (! type.isInterface()){
101 // if (referencedClass.isAssignableFrom(type)||
102 // type.isAssignableFrom(referencedClass) && CdmBase.class.isAssignableFrom(type)){
103 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
104 // }
105 // //interface
106 // }else if (type.isAssignableFrom(referencedClass)){
107 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
108 // }else if (Collection.class.isAssignableFrom(type)){
109 //
110 // if (checkIsSetOfType(field, referencedClass, type) == true){
111 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, true);
112 // }
113 // }
114 //// Class[] interfaces = referencedClass.getInterfaces();
115 //// for (Class interfaze: interfaces){
116 //// if (interfaze == type){
117 ////// if(interfaze.isAssignableFrom(returnType)){
118 //// handleSingleClass(interfaze, type, field, cdmClass, result, referencedCdmBase);
119 //// }
120 //// }
121 // }
122 // }
123 // return result;
124 // } catch (Exception e) {
125 // e.printStackTrace();
126 // throw new RuntimeException(e);
127 // }
128 //
129 // }
130 //
131 // private boolean checkIsSetOfType(Field field, Class referencedClass, Class<?> type){
132 // Type genericType = (ParameterizedTypeImpl)field.getGenericType();
133 // if (genericType instanceof ParameterizedTypeImpl){
134 // ParameterizedTypeImpl paraType = (ParameterizedTypeImpl)genericType;
135 // paraType.getRawType();
136 // Type[] arguments = paraType.getActualTypeArguments();
137 // //logger.debug(arguments.length);
138 // if (arguments.length == 1){
139 // Class collectionClass;
140 // try {
141 // if (arguments[0] instanceof Class){
142 // collectionClass = (Class)arguments[0];
143 // }else if(arguments[0] instanceof TypeVariableImpl){
144 // TypeVariableImpl typeVariable = (TypeVariableImpl)arguments[0];
145 // GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
146 // collectionClass = (Class)genericDeclaration;
147 // }else{
148 // logger.warn("Unknown Type");
149 // return false;
150 // }
151 // if (CdmBase.class.isAssignableFrom(collectionClass) && collectionClass.isAssignableFrom(referencedClass) ){
152 // return true;
153 // }
154 // } catch (Exception e) {
155 // logger.warn(e.getMessage());
156 // }
157 // }else{
158 // logger.warn("Length of arguments <> 1");
159 // }
160 // }else{
161 // logger.warn("Not a generic type of type ParameterizedTypeImpl");
162 // }
163 // return false;
164 // }
165 //
166 //
167 //
168 //
169 // private boolean handleSingleClass(Class itemClass, Class type, Field field, Class cdmClass, Set<CdmBase> result,CdmBase value, boolean isCollection){
170 // if (! Modifier.isStatic(field.getModifiers())){
171 // String methodName = StringUtils.rightPad(field.getName(), 30);
172 // String className = StringUtils.rightPad(cdmClass.getSimpleName(), 30);
173 // String returnTypeName = StringUtils.rightPad(type.getSimpleName(), 30);
174 //
175 // logger.debug(methodName + "\t\t" + className + "\t\t" + returnTypeName);
176 //// result_old.add(method);
177 // result.addAll(getCdmBasesByFieldAndClass(field, itemClass, cdmClass, value, isCollection));
178 // }
179 // return true;
180 // }
181 //
182 // private Set<Field> getFields(Class clazz){
183 // Set<Field> result = new HashSet<Field>();
184 // for (Field field: clazz.getDeclaredFields()){
185 // if (!Modifier.isStatic(field.getModifiers())){
186 // result.add(field);
187 // }
188 // }
189 // Class superclass = clazz.getSuperclass();
190 // if (CdmBase.class.isAssignableFrom(superclass)){
191 // result.addAll(getFields(superclass));
192 // }
193 // return result;
194 // }
195 //
196 // private Set<CdmBase> getCdmBasesByFieldAndClass(Field field, Class itemClass, Class otherClazz, CdmBase item, boolean isCollection){
197 // Set<CdmBase> result = new HashSet<CdmBase>();
198 // if (isCollection){
199 // result.addAll(genericDao.getCdmBasesWithItemInCollection(itemClass, otherClazz, field.getName(), item));
200 // }else{
201 // result.addAll(genericDao.getCdmBasesByFieldAndClass(otherClazz, field.getName(), item));
202 // }
203 // return result;
204 // }
205
206 public List getHqlResult(String hqlQuery){
207 return genericDao.getHqlResult(hqlQuery);
208 }
209
210 /* (non-Javadoc)
211 * @see eu.etaxonomy.cdm.api.service.ICommonService#merge(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergeStragegy)
212 */
213 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond, IMergeStrategy mergeStrategy) throws MergeException {
214 if (mergeStrategy == null){
215 mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
216 }
217 genericDao.merge((CdmBase)mergeFirst, (CdmBase)mergeSecond, mergeStrategy);
218 }
219
220
221 public <T extends IMatchable> List<T> findMatching(T objectToMatch, IMatchStrategy matchStrategy) throws MatchException {
222 if (matchStrategy == null){
223 matchStrategy = DefaultMatchStrategy.NewInstance(((objectToMatch).getClass()));
224 }
225 return genericDao.findMatching(objectToMatch, matchStrategy);
226 }
227
228
229
230 /* (non-Javadoc)
231 * @see eu.etaxonomy.cdm.api.service.IService#list(java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
232 */
233 public <TYPE extends OriginalSourceBase> Pager<TYPE> list(Class<TYPE> type,
234 Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
235 List<String> propertyPaths) {
236 logger.warn("Not yet implemented");
237 return null;
238 }
239
240 /* (non-Javadoc)
241 * @see eu.etaxonomy.cdm.api.service.ICommonService#saveAll(java.util.Collection)
242 */
243 @Transactional(readOnly = false)
244 public void saveAllMetaData(Collection<CdmMetaData> metaData) {
245 Iterator<CdmMetaData> iterator = metaData.iterator();
246 while(iterator.hasNext()){
247 CdmMetaData cdmMetaData = iterator.next();
248 genericDao.saveMetaData(cdmMetaData);
249 }
250 }
251
252 /* (non-Javadoc)
253 * @see eu.etaxonomy.cdm.api.service.ICommonService#getCdmMetaData()
254 */
255 public Map<MetaDataPropertyName, CdmMetaData> getCdmMetaData() {
256 Map<MetaDataPropertyName, CdmMetaData> result = new HashMap<MetaDataPropertyName, CdmMetaData>();
257 List<CdmMetaData> metaDataList = genericDao.getMetaData();
258 for (CdmMetaData metaData : metaDataList){
259 MetaDataPropertyName propertyName = metaData.getPropertyName();
260 result.put(propertyName, metaData);
261 }
262 return result;
263 }
264
265 /**
266 * Checks whether the current database schema is compatible with the editor version.
267 * @throws DatabaseSchemaMismatchException
268 */
269 public boolean isDatabaseSchemaCompatible() {
270
271 Map<MetaDataPropertyName, CdmMetaData> allCommonData = getCdmMetaData();
272
273 if (allCommonData.containsKey(MetaDataPropertyName.DB_SCHEMA_VERSION)) {
274
275 String currentSchemaVersion = getCurrentSchemaVersion(allCommonData);
276 String databaseSchemaVersion = getDatabaseSchemaVersion(allCommonData);
277
278 if (areStringsEqual(currentSchemaVersion, databaseSchemaVersion)) {
279 return true;
280 }
281 }
282 return false;
283 }
284
285 /**
286 * Compares version numbers of the current schema version with the database schema version.
287 * @param currentSchemaVersion
288 * @param databaseSchemaVersion
289 * @throws DatabaseSchemaMismatchException
290 */
291 private boolean areStringsEqual(String first,
292 String second) {
293 return first.equals(second);
294 }
295
296 /**
297 * Gets the database schema version.
298 * @param allCommonData
299 * @return database schema version.
300 */
301 private String getDatabaseSchemaVersion(
302 Map<MetaDataPropertyName, CdmMetaData> allCommonData) {
303 // Get database schema version
304 CdmMetaData metaData = allCommonData.get(MetaDataPropertyName.DB_SCHEMA_VERSION);
305 String versionProperty = metaData.getMetaDataPropertyName();
306 String databaseSchemaVersion = getVersion(versionProperty);
307 return databaseSchemaVersion;
308 }
309
310 /**
311 * Gets the current schema version.
312 * @param allCommonData
313 * @return Current schema version.
314 */
315 private String getCurrentSchemaVersion(
316 Map<MetaDataPropertyName, CdmMetaData> allCommonData) {
317 // Get current schema version
318 String versionProperty = allCommonData.get(MetaDataPropertyName.DB_SCHEMA_VERSION).getValue();
319 String currentSchemaVersion = getVersion(versionProperty);
320 return currentSchemaVersion;
321 }
322
323 /**
324 * @param versionProperty
325 * @return Version number as string.
326 */
327 private String getVersion(String versionProperty) {
328 return versionProperty.substring(0, secondIndexOf(versionProperty, ".", 2));
329 }
330
331 /**
332 * Calculates the n-th occurrence of a string.
333 * @param versionProperty
334 * @return Index of N-th occurence of a string.
335 */
336 private int secondIndexOf(String versionProperty, String pattern, int occurence) {
337 int currentIndex = -1;
338 for (int i=0; i<occurence; i++) {
339 currentIndex = versionProperty.indexOf(pattern, currentIndex + 1);
340 }
341 return currentIndex;
342 }
343
344 }