3 * Copyright (C) 2007 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.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.util
.Collection
;
14 import java
.util
.HashMap
;
15 import java
.util
.Iterator
;
16 import java
.util
.List
;
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
;
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
;
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);
53 IOriginalSourceDao originalSourceDao
;
56 ICdmGenericDao genericDao
;
60 protected void setDao(IOriginalSourceDao dao
) {
65 * @see eu.etaxonomy.cdm.api.service.ICommonService#getSourcedObjectById(java.lang.String, java.lang.String)
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();
73 List
<IdentifiableEntity
> list
= originalSourceDao
.findOriginalSourceByIdInSource(clazz
, idInSource
, idNamespace
);
74 if (! list
.isEmpty()){
82 * @see eu.etaxonomy.cdm.api.service.ICommonService#getReferencingObjects(eu.etaxonomy.cdm.model.common.CdmBase)
84 public Set
<CdmBase
> getReferencingObjects(CdmBase referencedCdmBase
){
85 return this.genericDao
.getReferencingObjects(referencedCdmBase
);
88 // Set<Class<? extends CdmBase>> allCdmClasses = genericDao.getAllCdmClasses(false); //findAllCdmClasses();
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());
95 // for (Class<? extends CdmBase> cdmClass : allCdmClasses){
96 // Set<Field> fields = getFields(cdmClass);
97 // for (Field field: fields){
98 // Class<?> type = field.getType();
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);
106 // }else if (type.isAssignableFrom(referencedClass)){
107 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
108 // }else if (Collection.class.isAssignableFrom(type)){
110 // if (checkIsSetOfType(field, referencedClass, type) == true){
111 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, true);
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);
124 // } catch (Exception e) {
125 // e.printStackTrace();
126 // throw new RuntimeException(e);
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;
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;
148 // logger.warn("Unknown Type");
151 // if (CdmBase.class.isAssignableFrom(collectionClass) && collectionClass.isAssignableFrom(referencedClass) ){
154 // } catch (Exception e) {
155 // logger.warn(e.getMessage());
158 // logger.warn("Length of arguments <> 1");
161 // logger.warn("Not a generic type of type ParameterizedTypeImpl");
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);
175 // logger.debug(methodName + "\t\t" + className + "\t\t" + returnTypeName);
176 //// result_old.add(method);
177 // result.addAll(getCdmBasesByFieldAndClass(field, itemClass, cdmClass, value, isCollection));
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);
189 // Class superclass = clazz.getSuperclass();
190 // if (CdmBase.class.isAssignableFrom(superclass)){
191 // result.addAll(getFields(superclass));
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));
201 // result.addAll(genericDao.getCdmBasesByFieldAndClass(otherClazz, field.getName(), item));
206 public List
getHqlResult(String hqlQuery
){
207 return genericDao
.getHqlResult(hqlQuery
);
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)
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());
217 genericDao
.merge((CdmBase
)mergeFirst
, (CdmBase
)mergeSecond
, mergeStrategy
);
221 public <T
extends IMatchable
> List
<T
> findMatching(T objectToMatch
, IMatchStrategy matchStrategy
) throws MatchException
{
222 if (matchStrategy
== null){
223 matchStrategy
= DefaultMatchStrategy
.NewInstance(((objectToMatch
).getClass()));
225 return genericDao
.findMatching(objectToMatch
, matchStrategy
);
231 * @see eu.etaxonomy.cdm.api.service.IService#list(java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
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");
241 * @see eu.etaxonomy.cdm.api.service.ICommonService#saveAll(java.util.Collection)
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
);
253 * @see eu.etaxonomy.cdm.api.service.ICommonService#getCdmMetaData()
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
);
266 * Checks whether the current database schema is compatible with the editor version.
267 * @throws DatabaseSchemaMismatchException
269 public boolean isDatabaseSchemaCompatible() {
271 Map
<MetaDataPropertyName
, CdmMetaData
> allCommonData
= getCdmMetaData();
273 if (allCommonData
.containsKey(MetaDataPropertyName
.DB_SCHEMA_VERSION
)) {
275 String currentSchemaVersion
= getCurrentSchemaVersion(allCommonData
);
276 String databaseSchemaVersion
= getDatabaseSchemaVersion(allCommonData
);
278 if (areStringsEqual(currentSchemaVersion
, databaseSchemaVersion
)) {
286 * Compares version numbers of the current schema version with the database schema version.
287 * @param currentSchemaVersion
288 * @param databaseSchemaVersion
289 * @throws DatabaseSchemaMismatchException
291 private boolean areStringsEqual(String first
,
293 return first
.equals(second
);
297 * Gets the database schema version.
298 * @param allCommonData
299 * @return database schema version.
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
;
311 * Gets the current schema version.
312 * @param allCommonData
313 * @return Current schema version.
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
;
324 * @param versionProperty
325 * @return Version number as string.
327 private String
getVersion(String versionProperty
) {
328 return versionProperty
.substring(0, secondIndexOf(versionProperty
, ".", 2));
332 * Calculates the n-th occurrence of a string.
333 * @param versionProperty
334 * @return Index of N-th occurence of a string.
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);