/*
* Copyright (C) 2005-2012 BetaCONCEPT Limited
*
* This file is part of Astroboa.
*
* Astroboa is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Astroboa is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Astroboa. If not, see <http://www.gnu.org/licenses/>.
*/
package org.betaconceptframework.astroboa.client.dao;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.ValueType;
import org.betaconceptframework.astroboa.api.model.definition.CmsDefinition;
import org.betaconceptframework.astroboa.api.model.definition.CmsPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.ComplexCmsPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.ContentObjectTypeDefinition;
import org.betaconceptframework.astroboa.api.model.exception.CmsException;
import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType;
import org.betaconceptframework.astroboa.cache.DefinitionCacheManager;
import org.betaconceptframework.astroboa.cache.region.AstroboaDefinitionCacheRegion;
import org.betaconceptframework.astroboa.service.dao.DefinitionServiceDao;
import org.betaconceptframework.astroboa.util.PropertyPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
*
*/
public class CachedDefinitionServiceDao extends DefinitionServiceDao {
protected final Logger logger = LoggerFactory.getLogger(getClass());
//key is comprised of the following values
// path#output#prettyPrint For example
// eventObject.profile.title#XML#true
private ConcurrentMap<String, Object> definitionsPerPath = new ConcurrentHashMap<String, Object>();
public CachedDefinitionServiceDao(){
AstroboaDefinitionCacheRegion definitionCacheRegion = new AstroboaDefinitionCacheRegion();
definitionCacheRegion.setDefinitionCacheManager(new DefinitionCacheManager());
setDefinitionCacheRegion(definitionCacheRegion);
}
public void addAspectDefinitionToCache(
ComplexCmsPropertyDefinition aspectDefinition) throws Exception {
definitionCacheRegion.putDefinition(ValueType.Complex, aspectDefinition.getName(), aspectDefinition);
}
public void addContentTypeDefinitionToCache(
ContentObjectTypeDefinition contentTypeDefinition) throws Exception {
definitionCacheRegion.putDefinition(ValueType.ContentType, contentTypeDefinition.getName(), contentTypeDefinition);
}
public void cacheParentDefinition(String fullPropertyDefinitionPath,
CmsPropertyDefinition cmsPropertyDefinition) throws Exception {
CmsDefinition parentDefinition = cmsPropertyDefinition.getParentDefinition();
if (parentDefinition == null){
if (cmsPropertyDefinition instanceof ComplexCmsPropertyDefinition){
addAspectDefinitionToCache((ComplexCmsPropertyDefinition)cmsPropertyDefinition);
}
else{
throw new CmsException("Property "+fullPropertyDefinitionPath + " is simple and returned from remote server without a parent");
}
}
else{
if (parentDefinition instanceof ContentObjectTypeDefinition){
addContentTypeDefinitionToCache((ContentObjectTypeDefinition)parentDefinition);
}
else{
if (parentDefinition instanceof ComplexCmsPropertyDefinition){
cacheParentDefinition(fullPropertyDefinitionPath, (ComplexCmsPropertyDefinition)parentDefinition);
}
else{
throw new CmsException("Property "+parentDefinition.getQualifiedName() + " is "+parentDefinition.getValueType()+" where it should be Complex");
}
}
}
}
public <T> T getCmsDefinition(String fullPropertyDefinitionPath, ResourceRepresentationType<T> output, boolean prettyPrint) throws Exception{
if (StringUtils.isBlank(fullPropertyDefinitionPath) || output == null){
return null;
}
//If a definition instance is requested, use the methods provided by the DefinitionServiceDao
if (ResourceRepresentationType.DEFINITION_INSTANCE.equals(output)){
if (StringUtils.isBlank(fullPropertyDefinitionPath)){
return null;
}
PropertyPath propertyPath = new PropertyPath(fullPropertyDefinitionPath);
String firstPart = propertyPath.getPropertyName();
String restOfPath = propertyPath.getPropertyDescendantPath();
ContentObjectTypeDefinition contentObjectTypeDefinition = getContentObjectTypeDefinition(firstPart);
if (contentObjectTypeDefinition == null){
ComplexCmsPropertyDefinition aspectDefinition = getAspectDefinition(firstPart);
if (aspectDefinition != null){
if (StringUtils.isBlank(restOfPath)){
return (T) aspectDefinition;
}
else{
return (T) aspectDefinition.getChildCmsPropertyDefinition(restOfPath);
}
}
}
else{
if (StringUtils.isBlank(restOfPath)){
return (T) contentObjectTypeDefinition;
}
return (T) contentObjectTypeDefinition.getCmsPropertyDefinition(restOfPath);
}
}
//Search for definition in the local map
String key = constructKey(fullPropertyDefinitionPath, output, prettyPrint);
return (T) definitionsPerPath.get(key);
}
public <T> void cacheCmsDefinition(String fullPropertyDefinitionPath, T cmsDefinition, ResourceRepresentationType<T> output, boolean prettyPrint) throws Exception{
if (StringUtils.isBlank(fullPropertyDefinitionPath) || cmsDefinition == null || output == null){
return;
}
if (cmsDefinition instanceof CmsPropertyDefinition){
cacheParentDefinition(fullPropertyDefinitionPath, (CmsPropertyDefinition)cmsDefinition);
}
else if (cmsDefinition instanceof ContentObjectTypeDefinition){
addContentTypeDefinitionToCache((ContentObjectTypeDefinition)cmsDefinition);
}
else{
String key = constructKey(fullPropertyDefinitionPath, output, prettyPrint);
if (!definitionsPerPath.containsKey(key)){
definitionsPerPath.put(key, cmsDefinition);
}
}
}
private <T> String constructKey(String fullPropertyDefinitionPath, ResourceRepresentationType<T> output, boolean prettyPrint){
return fullPropertyDefinitionPath+"#"+output.toString()+"#"+prettyPrint;
}
}