/*
* 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.edit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.BinaryChannel;
import org.betaconceptframework.astroboa.api.model.ComplexCmsRootProperty;
import org.betaconceptframework.astroboa.api.model.ContentObject;
import org.betaconceptframework.astroboa.api.model.SimpleCmsProperty;
import org.betaconceptframework.astroboa.api.model.StringProperty;
import org.betaconceptframework.astroboa.api.model.ValueType;
import org.betaconceptframework.astroboa.api.model.definition.BinaryPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.SimpleCmsPropertyDefinition;
import org.betaconceptframework.astroboa.api.model.definition.StringFormat;
import org.betaconceptframework.astroboa.api.model.definition.StringPropertyDefinition;
import org.betaconceptframework.astroboa.console.jsf.visitor.CmsPropertyValidatorVisitor;
import org.betaconceptframework.astroboa.model.factory.CmsRepositoryEntityFactory;
import org.betaconceptframework.ui.jsf.utility.JSFUtilities;
import org.betaconceptframework.utility.PdfToTextExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.support.ServletContextResource;
/**
* Wraps a value of a SimpleCmsProperty in order
* to be successfully rendered and updated from JSF
* @author Savvas Triantafyllou (striantafillou@betaconcept.gr)
*
*/
/**
* @author Gregory Chomatas (gchomatas@betaconcept.com)
* @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
*
*/
public class SimpleCmsPropertyValueWrapper {
private final Logger logger = LoggerFactory.getLogger(getClass());
private int valueIndex = -1;
private SimpleCmsProperty simpleCmsProperty;
private BinaryChannel binaryChannelValue;
private CmsRepositoryEntityFactory cmsRepositoryEntityFactory;
private String mimeTypeIconFilePath;
private String unmanagedBinaryChannelRelativePath;
private PasswordVerifier passwordVerifier = null;
private CmsPropertyValidatorVisitor cmsPropertyValidatorVisitor;
private Object tempValue;
private boolean valueIsNull;
public SimpleCmsPropertyValueWrapper(SimpleCmsProperty simpleCmsProperty, int valueIndex,CmsRepositoryEntityFactory cmsRepositoryEntityFactory,
CmsPropertyValidatorVisitor cmsPropertyValidatorVisitor){
this.simpleCmsProperty = simpleCmsProperty;
this.valueIndex = valueIndex;
mimeTypeIconFilePath = null;
this.cmsRepositoryEntityFactory = cmsRepositoryEntityFactory;
this.cmsPropertyValidatorVisitor = cmsPropertyValidatorVisitor;
if (cmsPropertyValidatorVisitor != null && simpleCmsProperty instanceof StringProperty &&
((StringProperty)simpleCmsProperty).getPropertyDefinition() != null &&
((StringProperty)simpleCmsProperty).getPropertyDefinition().isPasswordType()){
if (this.cmsPropertyValidatorVisitor != null){
this.cmsPropertyValidatorVisitor.registerSimpleCmsPropertyOfPasswordType(this);
}
passwordVerifier = new PasswordVerifier(getLocalizedLabelOfFullPathFromCmsProperty());
}
}
public void reset() {
binaryChannelValue = null;
mimeTypeIconFilePath = null;
if (passwordVerifier!=null){
passwordVerifier.resetPasswords();
}
}
public Object getValue(){
if (tempValue != null){
return tempValue;
}
if (simpleCmsProperty != null){
Object value = null;
if (simpleCmsProperty.getPropertyDefinition().isMultiple()){
if (valueIndex >= simpleCmsProperty.getSimpleTypeValues().size()){
//Probably a blank value has been inserted. Return null value
//This is the normal case for primitive values.
//When it comes for non-primitive values (Topic, Space ,etc)
//it is possible that a new object will be created
return null;
}
else
value = simpleCmsProperty.getSimpleTypeValues().get(valueIndex);
}
else{
//Single value property.
value = simpleCmsProperty.getSimpleTypeValue();
}
if (value != null){
if (value instanceof Calendar){
return ((Calendar)value).getTime();
}
else if (value instanceof BinaryChannel){
binaryChannelValue = (BinaryChannel)value;
if (simpleCmsProperty.getPropertyDefinition() != null &&
simpleCmsProperty.getPropertyDefinition() instanceof BinaryPropertyDefinition &&
((BinaryPropertyDefinition)simpleCmsProperty.getPropertyDefinition()).isBinaryChannelUnmanaged() ){
unmanagedBinaryChannelRelativePath = binaryChannelValue.getRelativeFileSystemPath();
}
}
}
return value;
}
return null;
}
public void setValue(Object value){
if (simpleCmsProperty != null){
if (value != null){
valueIsNull = false;
if (value instanceof Date){
//Special case. Must create calendar instances
Calendar cal = Calendar.getInstance();
cal.setTime((Date)value);
value = cal;
}
else if (value instanceof String){
if (StringUtils.isBlank((String)value)){
value = null;
valueIsNull = true;
}
else{
if (ValueType.Long == simpleCmsProperty.getValueType()){
try {
value = Long.valueOf((String)value);
} catch (NumberFormatException e) {
setTemporaryValue(value);
return;
}
}
else if (ValueType.Double == simpleCmsProperty.getValueType()){
try {
value = Double.valueOf((String)value);
} catch (NumberFormatException e) {
setTemporaryValue(value);
return;
}
}
}
}
}
else{
valueIsNull = true;
}
if (simpleCmsProperty.getPropertyDefinition().isMultiple()){
if (valueIndex >= simpleCmsProperty.getSimpleTypeValues().size()){
//User has added a new value to list. Append list regardless of value index
//This is done to cover the following case
//Suppose list has already two values with indexes 0 and 1 and user
//adds a new value. The property value list has two values (index = 1) but
//value index of the value wrapper becomes 2.
//If we call method list.set(index, value)
//it will throw an exception. Thus it is safe to just add value to the
//end of the list if the value is not null
if (value != null) {
simpleCmsProperty.addSimpleTypeValue(value);
}
}
else{
simpleCmsProperty.getSimpleTypeValues().set(valueIndex, value);
}
}
else{
//Single value. Ignore value index and replace value
simpleCmsProperty.setSimpleTypeValue(value);
}
tempValue = null;
}
}
private void setTemporaryValue(Object value) {
tempValue = value;
cmsPropertyValidatorVisitor.registerInvalidSimpleCmsPropertyWithTempValue(this);
}
public boolean isImageMimeType(){
return binaryChannelValue != null && binaryChannelValue.getMimeType() != null &&
binaryChannelValue.getMimeType().startsWith("image");
}
// we need this in order to determine if we can show the image inline
public boolean isJPGorPNGorGIFImage(){
return binaryChannelValue != null && binaryChannelValue.getMimeType() != null &&
(binaryChannelValue.getMimeType().equals("image/jpeg") ||
binaryChannelValue.getMimeType().equals("image/png") ||
binaryChannelValue.getMimeType().equals("image/x-png") ||
binaryChannelValue.getMimeType().equals("image/gif"));
}
// we need this in order to determine if we can show the text of the pdf file inline
public boolean isPdfFile(){
return binaryChannelValue != null && binaryChannelValue.getMimeType() != null &&
(binaryChannelValue.getMimeType().equals("application/pdf") ||
binaryChannelValue.getMimeType().equals("application/x-pdf"));
}
// we need this in order to determine if we can show the text of the word file inline
public boolean isWordFile(){
return binaryChannelValue != null && binaryChannelValue.getMimeType() != null &&
(binaryChannelValue.getMimeType().equals("application/msword"));
}
public String getPlainTextPreviewOfPdfFile() {
PdfToTextExtractor pdfToTextExtractor = new PdfToTextExtractor();
try {
return pdfToTextExtractor.extractPdfToText(binaryChannelValue.getContent(), 1, 0, false, false, null);
}
catch (Exception e) {
logger.error("Error while converting pdf file to text" , e);
return null;
}
}
public String getMimeTypeIconPath() {
if (mimeTypeIconFilePath != null)
return mimeTypeIconFilePath;
// The Default Icon if we do not find a more appropriate one
String mimeTypeIconPath = "images/cms-icons/text1.png";
if (binaryChannelValue != null && binaryChannelValue.getMimeType() != null){
try{
mimeTypeIconFilePath = "images/mime-type_icons/"+binaryChannelValue.getMimeType()+".png";
ServletContextResource mimeTypeIconResource = new ServletContextResource((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext(), mimeTypeIconFilePath);
if (mimeTypeIconResource.exists())
return mimeTypeIconFilePath;
else{
logger.warn("No icon found for mime type "+ binaryChannelValue.getMimeType() + " for file "+ binaryChannelValue.getSourceFilename());
mimeTypeIconFilePath = mimeTypeIconPath;
}
}
catch(Exception e){
logger.error("No icon found for mime type "+ binaryChannelValue.getMimeType() + " for file "+ binaryChannelValue.getSourceFilename(), e);
mimeTypeIconFilePath = mimeTypeIconPath;
}
}
return mimeTypeIconFilePath;
}
public boolean isRichTextCmsProperty() {
return simpleCmsProperty != null
&& ValueType.String == simpleCmsProperty.getValueType()
&& StringFormat.RichText == ((StringPropertyDefinition)simpleCmsProperty.getPropertyDefinition()).getStringFormat();
}
public String getSimpleCmsPropertyLocalizedLabelOfFullPathforLocale() {
if (simpleCmsProperty !=null)
return simpleCmsProperty.getLocalizedLabelOfFullPathforLocaleWithDelimiter(JSFUtilities.getLocaleAsString(), " > ");
return "";
}
public String getFirstSentenceOfRichTextValue(){
if (!isRichTextCmsProperty())
return "";
String richText = (String) getValue();
if (StringUtils.isBlank(richText))
return null;
//Get first 200 characters and strip html tags
String firstSentence = StringUtils.substring(richText.replaceAll("<(.|\n)+?>", ""), 0, 200);
if (firstSentence != null){
return firstSentence + "...";
}
return firstSentence;
}
public BinaryChannel getBinaryChannelValue() {
if (binaryChannelValue == null)
getValue();
return binaryChannelValue;
}
public boolean isContentAvailable(){
return getBinaryChannelValue() != null //BinaryChannel value must exist
&& (
binaryChannelValue.contentExists() // BinaryChannel value has a relative system path
|| binaryChannelValue.isNewContentLoaded() //BinaryChannel is new and content exists
);
}
public BinaryChannel getNewBinaryChannelValue() {
binaryChannelValue = cmsRepositoryEntityFactory.newBinaryChannel();
binaryChannelValue.setName(simpleCmsProperty.getName());
return binaryChannelValue;
}
public String getLocalizedLabelForCurrentLocaleForContentObjectTypeValue(){
if (simpleCmsProperty != null && simpleCmsProperty.getValueType() == ValueType.ObjectReference){
Object contentObject = getValue();
if (contentObject != null){
try{
return ((ContentObject)contentObject).getTypeDefinition().getDisplayName().getLocalizedLabelForLocale(JSFUtilities.getLocaleAsString());
}
catch(Exception e){
logger.error("", e);
return "";
}
}
}
return "";
}
public boolean isThumbnailPropertyValueWrapper(){
return "thumbnail".equals(simpleCmsProperty.getName()) //Property should be named after 'thumbnail'
&& ( simpleCmsProperty.getParentProperty() instanceof ComplexCmsRootProperty);
}
public void setMimeTypeIconFilePath(String mimeTypeIconFilePath) {
this.mimeTypeIconFilePath = mimeTypeIconFilePath;
}
public void addDefaultValue() {
if (simpleCmsProperty != null && simpleCmsProperty.getValueType() != null){
Object defaultValue = null;
if (simpleCmsProperty.getPropertyDefinition() != null && ((SimpleCmsPropertyDefinition)simpleCmsProperty.getPropertyDefinition()).isSetDefaultValue() ){
defaultValue = ((SimpleCmsPropertyDefinition)simpleCmsProperty.getPropertyDefinition()).getDefaultValue();
}
/*if (defaultValue == null){
switch (simpleCmsProperty.getValueType()) {
case Binary:
defaultValue = getOrCreateNewBinaryChannelValue();
break;
case Boolean:
defaultValue = Boolean.TRUE;
break;
case Date:
defaultValue = Calendar.getInstance(JSFUtilities.getTimeZone(), JSFUtilities.getLocale());
break;
case Double:
case Long:
case String:
break;
case Topic:
case ContentObject:
logger.warn("Try to add blank value from SimpleCmsPropertyValueWrapper where there is a specific value wrapper for "+simpleCmsProperty.getValueType());
break;
case RepositoryUser:
case Space:
logger.warn("Try to add blank value for unsupported simple cms property type "+simpleCmsProperty.getValueType());
break;
default:
logger.warn("Try to add blank value for invalid simple cms property type "+simpleCmsProperty.getValueType());
break;
}
}*/
if (defaultValue != null){
setValue(defaultValue);
}
}
}
public void moveUp() {
valueIndex--;
}
public void moveDown() {
valueIndex++;
}
/**
* @return the unmanagedBinaryChannelRelativePath
*/
public String getUnmanagedBinaryChannelRelativePath() {
return unmanagedBinaryChannelRelativePath;
}
/**
* @param unmanagedBinaryChannelRelativePath the unmanagedBinaryChannelRelativePath to set
*/
public void setUnmanagedBinaryChannelRelativePath(
String unmanagedBinaryChannelRelativePath) {
this.unmanagedBinaryChannelRelativePath = unmanagedBinaryChannelRelativePath;
binaryChannelValue = cmsRepositoryEntityFactory.newUnmanagedBinaryChannel(unmanagedBinaryChannelRelativePath);
binaryChannelValue.setName(simpleCmsProperty.getName());
setValue(binaryChannelValue);
}
public List<String> verifyPassword(){
if (simpleCmsProperty instanceof StringProperty &&
((StringProperty)simpleCmsProperty).getPropertyDefinition() != null &&
((StringProperty)simpleCmsProperty).getPropertyDefinition().isPasswordType()){
if (passwordVerifier == null){
return Arrays.asList(JSFUtilities.getLocalizedMessage("application.unknown.error.message", null));
}
else{
String encryptedValue = passwordVerifier.newPasswordVerified(((StringProperty)simpleCmsProperty).getPropertyDefinition().getPasswordEncryptor(),
(String)getValue());
if (encryptedValue != null){
setValue(encryptedValue);
return new ArrayList<String>();
}
else{
return passwordVerifier.getValidatorMessages();
}
}
}
return new ArrayList<String>();
}
/**
* @return the passwordVerifier
*/
public PasswordVerifier getPasswordVerifier() {
return passwordVerifier;
}
private String getLocalizedLabelOfFullPathFromCmsProperty(){
return (simpleCmsProperty == null ? "" :
simpleCmsProperty.getLocalizedLabelOfFullPathforLocaleWithDelimiter(JSFUtilities.getLocaleAsString(), " > "));
}
public String getFullPropertyPath() {
return ( simpleCmsProperty != null && simpleCmsProperty.getPropertyDefinition() != null ?
simpleCmsProperty.getPropertyDefinition().getFullPath() :
"" );
}
public void clearPasswords() {
if (passwordVerifier!= null){
passwordVerifier.resetPasswords();
}
}
public boolean isMultiple(){
return simpleCmsProperty!=null && simpleCmsProperty.getPropertyDefinition() !=null &&
simpleCmsProperty.getPropertyDefinition().isMultiple();
}
public int getValueIndex(){
return valueIndex;
}
public SimpleCmsProperty getSimpleCmsProperty() {
return simpleCmsProperty;
}
public boolean hasTempValue(){
return tempValue != null;
}
/**
* @param indexOf
*/
public void changeIndex(int index) {
valueIndex = index;
}
public boolean isValueSetNull(){
return valueIsNull;
}
}