/*
* Copyright 2010 Semafor Informatik & Energie AG, Basel, Switzerland
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.semafor.gendas.service;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.hibernate.stat.Statistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ch.semafor.gendas.dao.ElementDao;
import ch.semafor.gendas.dao.ElementTypeDao;
import ch.semafor.gendas.dao.PropertyTypeDao;
import ch.semafor.gendas.model.CoreException;
import ch.semafor.gendas.model.Element;
import ch.semafor.gendas.model.ElementType;
import ch.semafor.gendas.model.Modification;
import ch.semafor.gendas.model.PropertyType;
/**
* Persistence service for Java Beans
* @author tar
*
*/
@Service("persistenceService")
public class PersistenceManagerImpl implements PersistenceManager {
private Cache cache;
@Resource // NOPMD by wildi on 9/21/10 6:34 AM
ElementDao elementDao; // NOPMD by wildi on 9/21/10 6:35 AM
@Resource // NOPMD by wildi on 9/21/10 6:34 AM
ElementTypeDao elementTypeDao; // NOPMD by wildi on 9/21/10 6:30 AM
@Resource // NOPMD by wildi on 9/21/10 6:38 AM
PropertyTypeDao propertyTypeDao; // NOPMD by wildi on 9/21/10 6:30 AM
private final Logger logger = LoggerFactory // NOPMD by wildi on 9/21/10 6:34 AM
.getLogger(PersistenceManagerImpl.class);
public PersistenceManagerImpl(){
CacheManager cacheManager = CacheManager.create();
this.cache = cacheManager.getCache("BEAN_LOADER");
// logger.info("Cache created");
}
private Object getCachedObject( Long id, Long rev ){
if( cache != null ){
StringBuffer key=new StringBuffer(id.toString());
if( rev!=null ){
key.append('.');
key.append(rev.toString());
}
final net.sf.ehcache.Element cacheElement = cache.get(key);
if( cacheElement != null ){
// logger.info("found object {} in cache", key);
return cacheElement.getValue();
}
}
// logger.info("missing object {} in cache", key);
return null;
}
private void putCachedObject( Long id, Long rev, Object obj ){
if( cache != null ){
StringBuffer key=new StringBuffer(id.toString());
if( rev!=null ){
key.append('.');
key.append(rev.toString());
}
// logger.info("put object {}", key);
final net.sf.ehcache.Element cacheElement =
new net.sf.ehcache.Element(key, obj);
cache.put(cacheElement);
}
}
@SuppressWarnings("rawtypes") // NOPMD by wildi on 9/21/10 6:34 AM
@Transactional
public ElementType createElementType(final Class beanClass) {
final ElementType t = new ElementTypeCreator(elementTypeDao, propertyTypeDao).create(beanClass); // NOPMD by wildi on 9/21/10 6:30 AM
elementTypeDao.save(t);
return t;
}
@Transactional
public Element save(final Object bean, final Long id, final String idName, final String idVersion) // NOPMD by wildi on 9/21/10 6:30 AM
throws CoreException, ElementCreationException {
logger.info(bean.getClass().getCanonicalName());
final ElementCreator creator = new ElementCreator(elementTypeDao, elementDao, propertyTypeDao, idName, idVersion);
logger.debug("about to create element tree for {}", bean.toString());
final Element newElement = creator.create(bean,null);
logger.debug("created element tree: {}", bean.toString());
// eliminate empty nodes
newElement.crunch();
// do not change it, uses System.out.println
if( logger.isDebugEnabled()){
newElement.print(0, "new Element after crunch()");
}
Element element=null;
if( id!=null && id>0L ){
element = elementDao.get(id);
}
if( element == null ){
element = new Element( newElement.getElementType() );
}
element.resetAssigned();
element.assign( newElement, elementDao );
if( logger.isDebugEnabled()){
element.print(0, "Element after assign() before save()");
}
element = elementDao.save( element );
creator.resetMaps();
creator.setMatchingIdsAndVersions(bean, element, null);
putCachedObject(element.getId(), null, bean);
return element;
}
public List<Element> getAllElements() {
return elementDao.getAll();
}
@Transactional(readOnly=true)
public Object load(Long id, final String idName, final String idVersion) throws CoreException, ElementCreationException { // NOPMD by wildi on 9/21/10 6:30 AM
return load( id, null, idName, idVersion );
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // NOPMD by wildi on 9/21/10 6:34 AM
@Transactional(readOnly=true)
public Object load(final Long id, final Long revision, final String idName, final String idVersion) throws CoreException, ElementCreationException { // NOPMD by wildi on 9/21/10 6:30 AM
Object obj = getCachedObject(id, revision);
if( obj != null )
return obj;
final Element e = elementDao.get(id); // NOPMD by wildi on 9/21/10 6:30 AM
if( logger.isDebugEnabled()){
e.print(0,"loaded element id " + id);
}
try {
final Class clazz = Class.forName(e.getElementType().getName());
final Constructor constr = clazz.getConstructor();
final Object bean = constr.newInstance();
final ElementCreator creator = new ElementCreator(elementTypeDao, elementDao, propertyTypeDao, idName, idVersion);
obj = creator.load(e, revision, bean, clazz);
putCachedObject(id, revision, obj);
return obj;
} catch( ClassNotFoundException ex){
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:35 AM
} catch (SecurityException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:36 AM
} catch (NoSuchMethodException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:36 AM
} catch (IllegalArgumentException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:35 AM
} catch (InstantiationException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:36 AM
} catch (IllegalAccessException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:39 AM
} catch (InvocationTargetException ex) {
throw new ElementCreationException(ex.getMessage()); // NOPMD by wildi on 9/21/10 6:39 AM
}
}
@Transactional(readOnly=true)
public List<Modification> getHistories(final Long id){ // NOPMD by wildi on 9/21/10 6:35 AM
final Element e = elementDao.get(id); // NOPMD by wildi on 9/21/10 6:35 AM
return new ArrayList<Modification>(e.getHistories());
}
@Transactional(readOnly=true)
public Long getLastRevision(final Long id){ // NOPMD by wildi on 9/21/10 6:35 AM
try{
final Element e = elementDao.get(id); // NOPMD by wildi on 9/21/10 6:35 AM
final Modification h = e.getLastHistory(); // NOPMD by wildi on 9/21/10 6:37 AM
return h.getRevision(); // NOPMD by wildi on 9/21/10 6:27 AM
}
catch(CoreException e){
//ToDO, PMD:AvoidPrintStackTrace
e.printStackTrace();
}
return null;
}
//ToDo, PMD:LooseCoupling
@SuppressWarnings({ "unchecked", "rawtypes" })
@Transactional(readOnly=true)
public List findDomainObjectsByArgs(final Class beanClass, final Map<String, String> args ,
final Map<String, Map<String, String>> childargs,
final String id, final String idVersion) throws ElementCreationException { // NOPMD by wildi on 9/21/10 6:37 AM
final List objectsList = new ArrayList();
try{
logger.debug("searching elements {} with id {}", beanClass.getCanonicalName(), id); // NOPMD by wildi on 9/21/10 6:34 AM
final List<Element> elements=elementDao.findElementsByArgs(beanClass.getCanonicalName(), args, childargs);
logger.debug("Total {} of {}", elements.size(), beanClass.getCanonicalName());
for (Element e: elements) {
// only elements of beanClass:
if( logger.isDebugEnabled()){
e.print(0, "about to create object");
}
objectsList.add(load(e.getId(), id, idVersion));
}
} catch (SecurityException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:39 AM
} catch (IllegalArgumentException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:39 AM
} catch (CoreException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:40 AM
}
return objectsList;
}
@SuppressWarnings("rawtypes")
public List getAllElementsByPropertyValue(final Class beanClass, final String prop, final String val ) {
List<Element> elements= elementDao.findByTypeAndPropertyTypeAndStringLike(beanClass.getCanonicalName(), prop, val);
return elements ;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Transactional(readOnly=true)
public List getAllObjectsByPropertyValue(final Class beanClass, final String prop, final String val,
final String id, final String idVersion) throws ElementCreationException { // NOPMD by wildi on 9/21/10 6:37 AM
final List objectsList = new ArrayList();
try{
logger.debug("searching elements {} by prop {} = {}", new Object[] {beanClass.getCanonicalName(), prop, val});
final List<Element> elements=getAllElementsByPropertyValue(beanClass, prop, val);
logger.debug("Total {} of {}", elements.size(), beanClass.getCanonicalName());
for (Element e: elements) {
// only elements of beanClass:
if( logger.isDebugEnabled()){
e.print(0, "about to create object");
}
objectsList.add(load(e.getId(),id, idVersion));
}
} catch (SecurityException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:40 AM
} catch (IllegalArgumentException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:40 AM
} catch (CoreException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:41 AM
}
return objectsList;
}
@SuppressWarnings("rawtypes")
@Transactional(readOnly=true)
public int getCountOfObjectsByPropertyValue(final Class beanClass, final String prop, final String value) {
return elementDao.getCountByTypeAndPropertyTypeAndStringLike(beanClass.getCanonicalName(), prop, value);
}
@SuppressWarnings("rawtypes")
@Transactional(readOnly=true)
public int getCountOfObjectsBy2PropertyValues(final Class beanClass,
final String prop1, final String value1, final String prop2, final String value2) {
return elementDao.getCountByTypeAnd2PropertyTypesAndStringsLike(beanClass.getCanonicalName(), prop1, value1, prop2, value2);
}
//ToDo, PMD:LooseCoupling
@SuppressWarnings("rawtypes")
@Transactional(readOnly=true)
public int getCountDomainObjectsByArgs(final Class beanClass, final Map<String, String> args,
final Map<String, Map<String, String>>childargs) {
//false positive, FB: DLS_DEAD_LOCAL_STORE
List objectsList = new ArrayList();
objectsList=elementDao.findElementsByArgs(beanClass.getCanonicalName(), args, childargs);
return objectsList.size();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public List getAllObjectsByReference(final Class beanClass, final Object ref,
final String id, final String idVersion) throws ElementCreationException { // NOPMD by wildi on 9/21/10 6:37 AM
final List objectsList = new ArrayList();
try{
logger.debug("searching elements {} with id {}", beanClass.getCanonicalName(), id);
final ElementCreator creator = new ElementCreator(elementTypeDao, elementDao, propertyTypeDao, id, idVersion);
final Element eref = creator.create(ref, null);
for (Element e: elementDao.findByTypeAndReference(beanClass.getCanonicalName(), eref)) {
// only elements of beanClass:
objectsList.add(load(e.getId(),id,idVersion));
}
} catch (SecurityException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:41 AM
} catch (IllegalArgumentException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:41 AM
} catch (CoreException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:41 AM
}
return objectsList;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Transactional(readOnly=true)
public List getAllObjects(final Class beanClass, final String id, final String idVersion) throws ElementCreationException { // NOPMD by wildi on 9/21/10 6:37 AM
final List objectsList = new ArrayList();
try{
logger.debug("searching elements {} with id {}", beanClass.getCanonicalName(), id);
for (Element e: elementDao.findByType(beanClass.getCanonicalName())) {
// only elements of beanClass:
objectsList.add(load(e.getId(),id,idVersion));
}
} catch (SecurityException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:41 AM
} catch (IllegalArgumentException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:42 AM
} catch (CoreException e) {
throw new ElementCreationException(e.getMessage()); // NOPMD by wildi on 9/21/10 6:42 AM
}
return objectsList;
}
public void setElementDao(final ElementDao elementDao) {
this.elementDao = elementDao;
}
public void setElementTypeDao(final ElementTypeDao elementTypeDao) {
this.elementTypeDao = elementTypeDao;
}
public void setPropertyTypeDao(final PropertyTypeDao propertyTypeDao) {
this.propertyTypeDao = propertyTypeDao;
}
@Transactional(readOnly=true)
public PropertyType getPropertyType(final String name) throws CoreException {
return propertyTypeDao.findByName(name);
}
@Transactional(readOnly=true)
public List<ElementType> getAllElementsTypes() {
return elementTypeDao.getAll();
}
@Transactional
public void delete(final Long id) { // NOPMD by wildi on 9/21/10 6:38 AM
elementDao.remove(id);
}
@Transactional(readOnly=true)
public Element getElement( Long id ){
return elementDao.get(id);
}
public Statistics getCacheStatistics(){
return elementDao.getStatistics();
}
}