/*
* 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.model.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.ComplexCmsProperty;
import org.betaconceptframework.astroboa.api.model.ComplexCmsRootProperty;
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.model.impl.definition.ComplexCmsPropertyDefinitionImpl;
import org.betaconceptframework.astroboa.model.impl.definition.ContentObjectTypeDefinitionImpl;
import org.betaconceptframework.astroboa.model.impl.definition.LocalizableCmsDefinitionImpl;
import org.betaconceptframework.astroboa.model.lazy.LazyLoader;
import org.betaconceptframework.astroboa.util.PropertyPath;
import org.slf4j.LoggerFactory;
/**
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
*
*/
public class ComplexCmsRootPropertyImpl extends ComplexCmsPropertyImpl<ComplexCmsPropertyDefinition,ComplexCmsProperty<? extends ComplexCmsPropertyDefinition, ? extends ComplexCmsProperty<?,?>>>
implements ComplexCmsRootProperty,AspectDefinitionManager, Serializable{
/**
*
*/
private static final long serialVersionUID = -6855093200508354921L;
private List<String> aspects = new ArrayList<String>();
private transient Map<String, ComplexCmsPropertyDefinition> aspectDefinitions = new HashMap<String, ComplexCmsPropertyDefinition>();
private String contentObjectSystemName;
public void loadAspectDefinition(String aspect) throws Exception{
//Check that aspect has not been defined in content type definition
if (getPropertyDefinition() == null)
throw new CmsException("ComplexCmsRootProperty is not attached to any definition");
//NOTE :In case content object type definition contains a property which refers to this aspect
//but property's name is different than aspect's one, the check will pass through
//and aspect will be added to content object
if (!getPropertyDefinition().hasChildCmsPropertyDefinition(aspect)){
//Get Aspect definition
ComplexCmsPropertyDefinition aspectDefinition = null;
LazyLoader lazyLoader = getLazyLoader();
if (lazyLoader !=null){
lazyLoader.activateClientContextForAuthenticationToken(authenticationToken);
aspectDefinition = (ComplexCmsPropertyDefinition) lazyLoader.getDefinitionService().getCmsDefinition(aspect, ResourceRepresentationType.DEFINITION_INSTANCE,false);
}
if (aspectDefinition == null){
LoggerFactory.getLogger(getClass()).warn("Definition for aspect "+ aspect + " was not found");
}
else{
//Attach aspect definition to Content Object
aspectDefinitions.put(aspectDefinition.getName(), aspectDefinition);
if (!aspects.contains(aspectDefinition.getName())){
aspects.add(aspectDefinition.getName());
}
}
}
}
public List<String> getAspects() {
return Collections.unmodifiableList(aspects);
}
public boolean hasAspect(String aspect) {
return aspects.contains(aspect);
}
@Override
public boolean removeChildProperty(String propertyPath){
final boolean propertyWasRemoved = super.removeChildProperty(propertyPath);
//Check if property is an aspect
PropertyPath path = new PropertyPath(propertyPath);
if (path.getPropertyDescendantPath() == null &&
path.getPropertyIndex() == PropertyPath.NO_INDEX){
String propertyName = path.getPropertyName();
if (aspects.contains(propertyName)){
//Remove aspect only if property is not there
if ( cmsPropertyHasBeenLoadedAndRemoved(propertyName) ||
! isChildPropertyLoaded(propertyName)){
if (aspectDefinitions.containsKey(propertyName)){
aspectDefinitions.remove(propertyName);
}
aspects.remove(propertyName);
}
}
}
return propertyWasRemoved;
}
@Override
protected CmsPropertyDefinition getChildPropertyDefinition(String childPropertyName){
if (getPropertyDefinition() != null){
CmsPropertyDefinition childCmsPropertyDefinition = getPropertyDefinition().getChildCmsPropertyDefinition(childPropertyName);
if (childCmsPropertyDefinition == null){
PropertyPath childPropertyPath = new PropertyPath(childPropertyName);
String firstChildInPathPropertyName = childPropertyPath.getPropertyName();
String restChildPropertyPath = childPropertyPath.getPropertyDescendantPath();
//Try Aspects
if (MapUtils.isNotEmpty(aspectDefinitions) && firstChildInPathPropertyName != null){
ComplexCmsPropertyDefinition firstChildCmsPropertyDefinition = aspectDefinitions.get(firstChildInPathPropertyName);
if (firstChildCmsPropertyDefinition != null && restChildPropertyPath != null){
//Multi path child property.
childCmsPropertyDefinition = firstChildCmsPropertyDefinition.getChildCmsPropertyDefinition(restChildPropertyPath);
}
else{
childCmsPropertyDefinition = firstChildCmsPropertyDefinition;
}
}
if (childCmsPropertyDefinition == null && firstChildInPathPropertyName != null){
//Try to load it as an aspect
try {
loadAspectDefinition(firstChildInPathPropertyName);
//Re check aspects
if (MapUtils.isNotEmpty(aspectDefinitions)){
ComplexCmsPropertyDefinition firstChildCmsPropertyDefinition = aspectDefinitions.get(firstChildInPathPropertyName);
if (firstChildCmsPropertyDefinition != null && restChildPropertyPath != null){
//Multi path child property.
childCmsPropertyDefinition = firstChildCmsPropertyDefinition.getChildCmsPropertyDefinition(restChildPropertyPath);
}
else{
childCmsPropertyDefinition = firstChildCmsPropertyDefinition;
}
if (childCmsPropertyDefinition == null && aspectDefinitions.containsKey(firstChildInPathPropertyName)){
//Definition was not found. Remove aspect since it is not needed any more
aspectDefinitions.remove(firstChildInPathPropertyName);
}
}
} catch (Exception e) {
//Property is not an aspect
LoggerFactory.getLogger(getClass()).warn("No definition found for property "+childPropertyName+" in content object "+
getContentObjectId(), e);
}
if (childCmsPropertyDefinition == null){
LoggerFactory.getLogger(getClass()).warn("Found no definition for child property '{}' in property {} in content object {}",
new Object[]{childPropertyName , this.getFullPath(), getContentObjectId()});
}
}
}
return childCmsPropertyDefinition;
}
throw new CmsException("Property "+ getFullPath() +" is not complex.");
}
@Override
public boolean isChildPropertyDefined(String propertyPath) {
boolean isPropertyDefined = false;
isPropertyDefined = super.isChildPropertyDefined(propertyPath);
if (!isPropertyDefined && MapUtils.isNotEmpty(aspectDefinitions))
{
PropertyPath aspectPath = new PropertyPath(propertyPath);
String aspectName = aspectPath.getPropertyName();
//Check if there are any aspect definitions
if (aspectDefinitions.containsKey(aspectName))
{
//Aspect exists. Check to see if we need to go any further
String aspectDescendantPath = aspectPath.getPropertyDescendantPath();
if (StringUtils.isNotBlank(aspectDescendantPath))
{
//Check aspect's children definitions
return (aspectDefinitions.get(aspectName).hasChildCmsPropertyDefinition(aspectDescendantPath));
}
//No aspect children in aspect path. Definition for aspect was requested ad it was found
return true;
}
}
return isPropertyDefined;
}
@Override
public Map<String, ComplexCmsPropertyDefinition> getAspectDefinitions() {
return Collections.unmodifiableMap(aspectDefinitions);
}
//Override deserialization process to inject
//and lazyLoader
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
//Deserialize bean normally
ois.defaultReadObject();
//Inject lazyLoader
LazyLoader lazyLoader = getLazyLoader();
if (lazyLoader != null){
lazyLoader.activateClientContextForAuthenticationToken(authenticationToken);
//In this case fullPropertyDefinitionPath is the name of content type
ContentObjectTypeDefinition contentTypeDefinition = (ContentObjectTypeDefinition) lazyLoader.getDefinitionService().getCmsDefinition(fullPropertyDefinitionPath, ResourceRepresentationType.DEFINITION_INSTANCE,false);
if (contentTypeDefinition != null){
setPropertyDefinition(new ComplexCmsPropertyDefinitionImpl(contentTypeDefinition.getQualifiedName(),
((LocalizableCmsDefinitionImpl)contentTypeDefinition).cloneDescription(),
((LocalizableCmsDefinitionImpl)contentTypeDefinition).cloneDisplayName(), false,false,true, null, null, null, null,
((ContentObjectTypeDefinitionImpl)contentTypeDefinition).getComplexPropertyDefinitionHelper(),
((ContentObjectTypeDefinitionImpl)contentTypeDefinition).getDefinitionFileURI(),
contentTypeDefinition.getPropertyPathsWhoseValuesCanBeUsedAsALabel(), true,
null, contentTypeDefinition.getName(), true));
}
//Load all aspects
aspectDefinitions = new HashMap<String, ComplexCmsPropertyDefinition>();
if (aspects != null){
for (String aspect : aspects){
try {
loadAspectDefinition(aspect);
} catch (Exception e) {
throw new IOException(e);
}
}
}
}
}
@Override
public String getContentObjectId() {
return getId();
}
@Override
public String getContentObjectSystemName() {
return contentObjectSystemName;
}
public void setContentObjectSystemName(String contentObjectSystemName) {
this.contentObjectSystemName = contentObjectSystemName;
}
}