/**
* Copyright (C) 2005-2007 BetaCONCEPT LP.
*
* This program 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 2
* of the License, or (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* 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.console.jsf.richfaces;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.betaconceptframework.astroboa.api.model.BinaryChannel;
import org.betaconceptframework.astroboa.api.model.BinaryProperty;
import org.betaconceptframework.astroboa.api.model.CmsProperty;
import org.betaconceptframework.astroboa.api.model.ComplexCmsProperty;
import org.betaconceptframework.astroboa.api.model.SimpleCmsProperty;
import org.betaconceptframework.astroboa.api.model.ValueType;
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.definition.LocalizableCmsDefinition;
import org.betaconceptframework.astroboa.api.model.definition.SimpleCmsPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.StringPropertyDefinition;
import org.betaconceptframework.ui.jsf.utility.JSFUtilities;
import org.richfaces.model.TreeNode;
/**
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* Created on Sept 10, 2007
*/
public class LazyLoadingContentObjectPropertyTreeNodeRichFaces extends LazyLoadingTreeNodeRichFaces {
private CmsProperty contentObjectProperty;
private LocalizableCmsDefinition contentObjectPropertyDefinition;
private BinaryChannel binaryChannel;
private Object contentObjectPropertyValue;
public LazyLoadingContentObjectPropertyTreeNodeRichFaces(String identifier, String description, TreeNode parent, String type, boolean leaf,
CmsProperty contentObjectProperty, LocalizableCmsDefinition contentObjectPropertyDefinition) {
super(identifier, description, parent, type, leaf);
this.contentObjectProperty = contentObjectProperty;
this.contentObjectPropertyDefinition = contentObjectPropertyDefinition;
}
public LazyLoadingContentObjectPropertyTreeNodeRichFaces(String identifier, String description, TreeNode parent, String type, boolean leaf,
CmsProperty contentObjectProperty, LocalizableCmsDefinition contentObjectPropertyDefinition, BinaryChannel binaryChannel) {
super(identifier, description, parent, type, leaf);
this.contentObjectProperty = contentObjectProperty;
this.contentObjectPropertyDefinition = contentObjectPropertyDefinition;
this.binaryChannel = binaryChannel;
}
public LazyLoadingContentObjectPropertyTreeNodeRichFaces(String identifier, String description, TreeNode parent, String type, boolean leaf,
CmsProperty contentObjectProperty, LocalizableCmsDefinition contentObjectPropertyDefinition, Object contentObjectPropertyValue) {
super(identifier, description, parent, type, leaf);
this.contentObjectProperty = contentObjectProperty;
this.contentObjectPropertyDefinition = contentObjectPropertyDefinition;
this.contentObjectPropertyValue = contentObjectPropertyValue;
}
public Iterator<Map.Entry<String, TreeNode>> getChildren() {
// if this in not a leaf node and there are no children, try and retrieve them
if (!isLeaf() && children.size() == 0) {
logger.debug("retreive children of node: " + identifier);
// Five cases of tree node types which are not leaves (i.e. have children):
// - RootPropertyNode
// - ComplexTypeMultiValuePropertyNode
// - ComplexTypeSingleValuePropertyNode
// - SimpleTypeMultiValuePropertyNode
// - BinaryChannelMultiValuePropertyNode
if ("ComplexTypeSingleOccurrencePropertyNode".equals(type) || "ComplexTypeMultipleOccurrencesPropertyNode".equals(type) || "RootPropertyNode".equals(type)){
// get the child property definitions and generate nodes for each property
Collection<CmsPropertyDefinition> childPropertyDefinitions;
if (contentObjectPropertyDefinition instanceof ContentObjectTypeDefinition)
childPropertyDefinitions = ((ContentObjectTypeDefinition)contentObjectPropertyDefinition).getSortedChildCmsPropertyDefinitionsByAscendingOrderAndValueTypeAndLocale(JSFUtilities.getLocaleAsString()).values();
else
childPropertyDefinitions = ((ComplexCmsPropertyDefinition)contentObjectPropertyDefinition).getSortedChildCmsPropertyDefinitionsByAscendingOrderAndValueTypeAndLocale(JSFUtilities.getLocaleAsString()).values();
for (CmsPropertyDefinition childPropertyDefinition : childPropertyDefinitions) {
// profile and accessibility properties have a special treatment while viewing them so we exclude them from the tree.
if ("profile".equals(childPropertyDefinition.getName()) || "accessibility".equals(childPropertyDefinition.getName()))
continue;
// two cases: either simple type or complex type property. Aspect is considered a complex property as well
if (childPropertyDefinition.getValueType().equals(ValueType.Complex)) {
// two sub cases: either Single Occurrence or Multiple Occurrences Complex Type property
if (childPropertyDefinition.isMultiple()) {
// since definition indicates the property can have multiple occurrences we should retrieve the occurrences under this property path
// and generate for each one a tree node of type ComplexTypeMultipleOccurrencesPropertyNode
List<CmsProperty> childProperties = ((ComplexCmsProperty)contentObjectProperty).getChildPropertyList(childPropertyDefinition.getName());
if (CollectionUtils.isNotEmpty(childProperties)){
int index = 0;
for (CmsProperty childProperty : childProperties) {
addComplexTypeMultipleOccurrencesPropertyNode((ComplexCmsProperty)childProperty, (ComplexCmsPropertyDefinition)childPropertyDefinition, index);
index++;
}
}
}
else { // single occurrence
CmsProperty childProperty = ((ComplexCmsProperty)contentObjectProperty).getChildProperty(childPropertyDefinition.getName());
addComplexTypeSingleOccurrencePropertyNode((ComplexCmsProperty)childProperty, (ComplexCmsPropertyDefinition)childPropertyDefinition);
}
}
// A Binary type property is a Simple Type property but we retrieve the values differently. So we consider it another special case
else if (childPropertyDefinition.getValueType().equals(ValueType.Binary)) {
CmsProperty childProperty = ((ComplexCmsProperty)contentObjectProperty).getChildProperty(childPropertyDefinition.getName());
// two sub cases: either Single Value or Multiple values Binary Type property
if (childPropertyDefinition.isMultiple()) {
addChildPropertyNode(childProperty, childPropertyDefinition, "BinaryTypeMultiValuePropertyNode", false);
}
else {
addBinaryTypeSingleValuePropertyNode((BinaryProperty)childProperty, childPropertyDefinition);
}
}
else { //simple type property
CmsProperty childProperty = ((ComplexCmsProperty)contentObjectProperty).getChildProperty(childPropertyDefinition.getName());
// two sub cases: either Single Value or Multiple Value Simple Type property
if (childPropertyDefinition.isMultiple())
addChildPropertyNode(childProperty, childPropertyDefinition, "SimpleTypeMultiValuePropertyNode", false);
else {
addSimpleTypeSingleValuePropertyNode((SimpleCmsProperty)childProperty, childPropertyDefinition);
}
}
}
}
else if ("SimpleTypeMultiValuePropertyNode".equals(type)) {
// get property values and generate a OneOfMultipleValues node for each one
List<Object> propertyValues = ((SimpleCmsProperty)contentObjectProperty).getSimpleTypeValues();
if (propertyValues.isEmpty())
leaf = true;
else {
int valueListIndex = 0;
for (Object propertyValue : propertyValues) {
addSimplePropertyValueNode((SimpleCmsProperty)contentObjectProperty, (SimpleCmsPropertyDefinition)contentObjectPropertyDefinition, propertyValue, ((CmsPropertyDefinition)contentObjectPropertyDefinition).getValueType(), valueListIndex);
valueListIndex++;
}
}
}
else if ("BinaryTypeMultiValuePropertyNode".equals(type)) { // A Binary Type property is a Simple Type property but we retrieve the values differently since its values are Binary Channels. So we consider it another special case
// get Binary Channels and generate a OneOfMultipleBinaryChannels node for each one
List<BinaryChannel> binaryChannels = ((BinaryProperty)contentObjectProperty).getSimpleTypeValues();
if (binaryChannels.isEmpty())
leaf = true;
else {
int binaryChannelIndex = 0;
for (BinaryChannel binaryChannel : binaryChannels) {
addBinaryChannelNode(binaryChannel, binaryChannelIndex);
binaryChannelIndex++;
}
}
}
}
return children.entrySet().iterator();
}
public void addComplexTypeMultipleOccurrencesPropertyNode(ComplexCmsProperty childProperty, ComplexCmsPropertyDefinition childPropertyDefinition, int index) {
String locale = JSFUtilities.getLocaleAsString();
LazyLoadingContentObjectPropertyTreeNodeRichFaces childPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + ":" + childPropertyDefinition.getName() + ":" + index,
childPropertyDefinition.getDisplayName().getLocalizedLabelForLocale(locale) + "[" + index + "]",
this,
"ComplexTypeMultipleOccurrencesPropertyNode",
false,
childProperty,
childPropertyDefinition);
children.put(childPropertyTreeNode.identifier, childPropertyTreeNode);
}
public void addComplexTypeSingleOccurrencePropertyNode(ComplexCmsProperty childProperty, ComplexCmsPropertyDefinition childPropertyDefinition) {
String locale = JSFUtilities.getLocaleAsString();
LazyLoadingContentObjectPropertyTreeNodeRichFaces childPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + ":" + childPropertyDefinition.getName(),
childPropertyDefinition.getDisplayName().getLocalizedLabelForLocale(locale),
this,
"ComplexTypeSingleOccurrencePropertyNode",
false,
childProperty,
childPropertyDefinition);
children.put(childPropertyTreeNode.identifier, childPropertyTreeNode);
}
public void addChildPropertyNode(CmsProperty childProperty, CmsPropertyDefinition childPropertyDefinition, String nodeType, boolean leaf) {
String locale = JSFUtilities.getLocaleAsString();
LazyLoadingContentObjectPropertyTreeNodeRichFaces childPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + ":" + childPropertyDefinition.getName(),
childPropertyDefinition.getDisplayName().getLocalizedLabelForLocale(locale),
this,
nodeType,
leaf,
childProperty,
childPropertyDefinition);
children.put(childPropertyTreeNode.identifier, childPropertyTreeNode);
}
public void addSimplePropertyValueNode(SimpleCmsProperty childProperty, SimpleCmsPropertyDefinition childPropertyDefinition, Object propertyValue, ValueType valueType, int valueListIndex) {
String nodeType;
// some value types require special handling and thus we introduce a different type of node appending the value type to the default node type
switch (valueType) {
case Date:
case TopicReference:
nodeType = "OneOfMultipleValuesNode" + ":" + valueType.toString();
break;
default:
nodeType = "OneOfMultipleValuesNode";
break;
}
LazyLoadingContentObjectPropertyTreeNodeRichFaces childPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + "[" + valueListIndex +"]",
"[" + valueListIndex +"]" + valueType,
this,
nodeType,
true,
childProperty,
childPropertyDefinition,
propertyValue);
children.put(childPropertyTreeNode.identifier, childPropertyTreeNode);
}
public void addSimpleTypeSingleValuePropertyNode(SimpleCmsProperty childProperty, CmsPropertyDefinition childPropertyDefinition) {
String locale = JSFUtilities.getLocaleAsString();
String nodeType;
// some value types require special handling and thus we introduce a different type of node appending the value type to the default node type
switch (childPropertyDefinition.getValueType()) {
case Date:
case TopicReference:
nodeType = "SimpleTypeSingleValuePropertyNode" + ":" + childPropertyDefinition.getValueType().toString();
break;
case String:
if ("PlainText".equals(((StringPropertyDefinition)childPropertyDefinition).getStringFormat().toString()))
nodeType = "SimpleTypeSingleValuePropertyNode" + ":" + ((StringPropertyDefinition)childPropertyDefinition).getStringFormat();
else if ("RichText".equals(((StringPropertyDefinition)childPropertyDefinition).getStringFormat().toString()))
nodeType = "SimpleTypeSingleValuePropertyNode" + ":" + ((StringPropertyDefinition)childPropertyDefinition).getStringFormat();
else
nodeType = "SimpleTypeSingleValuePropertyNode" + ":" + "PlainText";
break;
default:
nodeType = "SimpleTypeSingleValuePropertyNode";
break;
}
LazyLoadingContentObjectPropertyTreeNodeRichFaces childPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + ":" + childPropertyDefinition.getName(),
childPropertyDefinition.getDisplayName().getLocalizedLabelForLocale(locale),
this,
nodeType,
true,
childProperty,
childPropertyDefinition,
childProperty.getSimpleTypeValue());
children.put(childPropertyTreeNode.identifier, childPropertyTreeNode);
}
public void addBinaryTypeSingleValuePropertyNode(BinaryProperty childProperty, CmsPropertyDefinition childPropertyDefinition) {
LazyLoadingContentObjectPropertyTreeNodeRichFaces binaryPropertyTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + ":" + childPropertyDefinition.getName(),
childPropertyDefinition.getDisplayName().getLocalizedLabelForLocale(JSFUtilities.getLocaleAsString()),
this,
"BinaryTypeSingleValuePropertyNode",
true,
childProperty,
childPropertyDefinition,
childProperty.getSimpleTypeValue());
children.put(binaryPropertyTreeNode.identifier, binaryPropertyTreeNode);
}
public void addBinaryChannelNode(BinaryChannel binaryChannel, int binaryChannelIndex) {
LazyLoadingContentObjectPropertyTreeNodeRichFaces binaryChannelTreeNode =
new LazyLoadingContentObjectPropertyTreeNodeRichFaces(
identifier + "[" + binaryChannelIndex +"]",
"[" + binaryChannelIndex +"]",
this,
"OneOfMultipleBinaryChannelsNode",
true,
null,
null,
binaryChannel);
children.put(binaryChannelTreeNode.identifier, binaryChannelTreeNode);
}
public CmsProperty getContentObjectProperty() {
return contentObjectProperty;
}
public BinaryChannel getBinaryChannel() {
return binaryChannel;
}
public LocalizableCmsDefinition getContentObjectPropertyDefinition() {
return contentObjectPropertyDefinition;
}
public Object getContentObjectPropertyValue() {
return contentObjectPropertyValue;
}
}