/*
* $Id: WebDAVCategories.java,v 1.35 2009/01/14 10:43:19 valdas Exp $
*
* Copyright (C) 2004 Idega. All Rights Reserved.
*
* This software is the proprietary information of Idega.
* Use is subject to license terms.
*
*/
package com.idega.content.presentation;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import org.apache.myfaces.component.html.ext.HtmlSelectBooleanCheckbox;
import com.idega.business.IBOLookup;
import com.idega.business.IBOLookupException;
import com.idega.content.bean.ManagedContentBeans;
import com.idega.content.business.WebDAVMetadataResource;
import com.idega.content.business.categories.CategoryBean;
import com.idega.content.data.ContentCategory;
import com.idega.content.data.ContentCategoryComparator;
import com.idega.core.localisation.business.ICLocaleBusiness;
import com.idega.presentation.IWBaseComponent;
import com.idega.presentation.IWContext;
import com.idega.presentation.Table;
import com.idega.presentation.ui.Label;
import com.idega.util.CoreConstants;
import com.idega.util.CoreUtil;
import com.idega.util.ListUtil;
import com.idega.util.StringHandler;
import com.idega.util.StringUtil;
import com.idega.webface.WFContainer;
import com.idega.webface.WFResourceUtil;
/**
* <p>
* Presentation object for the categories.<br>
* Displays checkboxes for the categoriues that an article can belong to, so that a user can
* select them accordingly.<br>
* Also allows for adding categories if needed
* </p>
* Last modified: $Date: 2009/01/14 10:43:19 $ by $Author: valdas $
*
* @author <a href="mailto:Joakim@idega.com">Joakim</a>
* @version $Revision: 1.35 $
*/
public class WebDAVCategories extends IWBaseComponent implements ManagedContentBeans, ActionListener{
//Constants
private static final String DEFAULT_CATEGORIES_BLOCK_ID = "categoriesBlock";
private static final int COLLUMNS = 3; //Number of collumns to display the categories in
private String resourcePath;
private String setCategories;
private boolean setOnParent=false;
private boolean displaySaveButton=true;
private boolean displayHeader=true;
private boolean addCategoryCreator = true;
private boolean needDisplayCategoriesSelection = true;
private boolean selectAnyCategory = false;
private boolean areCategoriesFetched = false;
private List<ContentCategory> selectedCategories = null;
private List<ContentCategory> notSelectedCategories = null;
private int localizedCategories = 0;
private String localeIdentity = null;
public WebDAVCategories() {
setId(DEFAULT_CATEGORIES_BLOCK_ID);
selectedCategories = new ArrayList<ContentCategory>();
notSelectedCategories = new ArrayList<ContentCategory>();
areCategoriesFetched = false;
}
public WebDAVCategories(String path, String localeIdentity){
this();
this.resourcePath = path;
this.localeIdentity = localeIdentity;
}
public void setResourcePath(String path){
this.resourcePath = path;
}
@Override
protected void initializeComponent(FacesContext context) {
add(getEditContainer(IWContext.getIWContext(context), false));
}
public void reset(){
getChildren().clear();
setInitialized(false);
IWContext iwc = IWContext.getInstance();
try {
WebDAVMetadataResource resource = (WebDAVMetadataResource) IBOLookup.getSessionInstance(iwc, WebDAVMetadataResource.class);
resource.clear();
} catch (IBOLookupException e) {
throw new RuntimeException(e);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
/**
* Creates the edit container
* @return editContainer
*/
private UIComponent getEditContainer(IWContext iwc, boolean submitted) {
WFContainer mainContainer = new WFContainer();
WFResourceUtil localizer = WFResourceUtil.getResourceUtilContent();
if(getDisplayHeader()){
mainContainer.add(localizer.getHeaderTextVB("categories"));
}
mainContainer.add(getCategoriesTable(iwc, submitted));
if (isAddCategoryCreator()) {
mainContainer.add(getAddCategoryContainer());
}
return mainContainer;
}
/**
* <p>
* TODO tryggvil describe method getAddHeader
* </p>
* @return
*/
private boolean getDisplayHeader() {
return this.displayHeader;
}
public void setDisplayHeader(boolean display){
this.displayHeader=display;
}
private List<ContentCategory> getSortedCategories(List<ContentCategory> categories, Locale locale) {
if (ListUtil.isEmpty(categories)) {
return categories;
}
Collections.sort(categories, new ContentCategoryComparator(locale));
return categories;
}
/**
* <p> Creates a table with checkboxes for all the available categories </p>
* @param resourcePath
* @return table
*/
private Table getCategoriesTable(IWContext iwc, boolean submitted) {
if (!areCategoriesFetched) {
getSelectedAndNotSelectedCategories(iwc);
}
Table categoriesTable = new Table();
int categoriesCount = 0;
Locale locale = getLocale(iwc);
List<ContentCategory> allCategories = new ArrayList<ContentCategory>(selectedCategories);
allCategories.addAll(notSelectedCategories);
allCategories = getSortedCategories(allCategories, locale);
if (ListUtil.isEmpty(allCategories)) {
return categoriesTable;
}
for (ContentCategory category: allCategories) {
HtmlSelectBooleanCheckbox categoryCheckBox = (HtmlSelectBooleanCheckbox) iwc.getApplication().createComponent(HtmlSelectBooleanCheckbox.COMPONENT_TYPE);
categoryCheckBox.setId(getCategoryKey(category));
if (selectedCategories.contains(category)) {
categoryCheckBox.setSelected(Boolean.TRUE);
}
else {
if (!submitted) {
if (notSelectedCategories.size() == 1 && selectedCategories.size() == 0 && selectAnyCategory) {
categoryCheckBox.setSelected(Boolean.TRUE);
}
}
}
categoriesTable.add(categoryCheckBox, categoriesCount%COLLUMNS + 1,categoriesCount/COLLUMNS + 1);
Label categoryName = new Label(category.getName(locale.toString()), categoryCheckBox);
categoriesTable.add(categoryName, categoriesCount%COLLUMNS + 1, categoriesCount/COLLUMNS + 1);
categoriesCount++;
}
categoriesTable.setColumns(Math.min(categoriesCount,COLLUMNS));
categoriesCount--;
categoriesTable.setRows(categoriesCount/COLLUMNS + 1);
if (getDisplaySaveButton()) {
// Add the save button
if(this.resourcePath!=null && this.resourcePath.length()>0) {
WFResourceUtil localizer = WFResourceUtil.getResourceUtilContent();
HtmlCommandButton addCategoryButton = localizer.getButtonVB(getSaveButtonId(), "save", this);
categoriesTable.add(addCategoryButton,1,categoriesCount/COLLUMNS + 2);
categoriesTable.setRows(categoriesCount/COLLUMNS + 2);
}
}
categoriesTable.setId(categoriesTable.getId() + "_ver");
categoriesTable.setStyleClass("wf_listtable");
return categoriesTable;
}
@Override
protected void updateComponent(FacesContext context) {
this.getChildren().clear();
add(getEditContainer(IWContext.getIWContext(context), true));
}
private Locale getLocale(IWContext iwc) {
Locale l = null;
if (localeIdentity == null) {
l = iwc.getCurrentLocale();
}
else {
l = ICLocaleBusiness.getLocaleFromLocaleString(localeIdentity);
}
if (l == null) {
l = Locale.ENGLISH;
}
return l;
}
/**
* <p>
* TODO tryggvil describe method getSaveButtonId
* </p>
* @return
*/
private String getSaveButtonId() {
return this.getId()+"_save";
}
/**
* <p>
* Gets the set categories, either from the resourcePath property or
* the setCategories property
* </p>
* @return
*/
private Collection<String> getSetCategoriesList() {
if (this.setCategories != null) {
return CategoryBean.getCategoriesFromString(this.setCategories);
} else if (this.resourcePath != null) {
IWContext iwuc = IWContext.getInstance();
try {
WebDAVMetadataResource resource = (WebDAVMetadataResource) IBOLookup.getSessionInstance(iwuc, WebDAVMetadataResource.class);
return resource.getCategories(this.resourcePath);
} catch (IBOLookupException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return null;
}
/**
* <p> Returns a container with "add category" UI</p>
* @return WFContainer
*/
private WFContainer getAddCategoryContainer() {
WFContainer container = new WFContainer();
WFResourceUtil localizer = WFResourceUtil.getResourceUtilContent();
//Text
HtmlOutputText addText = localizer.getTextVB("new_category");
container.add(addText);
//Input
HtmlInputText newCategoryInput = new HtmlInputText();
newCategoryInput.setSize(40);
newCategoryInput.setId(getAddCategoryInputId());
container.add(newCategoryInput);
//Button
HtmlCommandButton addCategoryButton = localizer.getButtonVB(getAddButtonId(), "add", this);
container.add(addCategoryButton);
return container;
}
/**
* <p>
* TODO tryggvil describe method getAddButtonId
* </p>
* @return
*/
private String getAddButtonId() {
return getId()+"_add";
}
/**
* <p>
* TODO tryggvil describe method getAddCategoryTextId
* </p>
* @return
*/
private String getAddCategoryInputId() {
return this.getId()+"_add_cat_input";
}
/**
* Will add the specified type - value metadata as a property to the selected resource.
*/
public void processAction(ActionEvent actionEvent) throws AbortProcessingException {
UIComponent comp = actionEvent.getComponent();
String id = comp.getId();
UIComponent superParent=comp;
WebDAVCategories realCategories = null;
while(superParent.getParent()!=null){
superParent=superParent.getParent();
if(superParent instanceof WebDAVCategories){
realCategories = (WebDAVCategories)superParent;
}
}
if(realCategories==null){
realCategories = (WebDAVCategories) superParent.findComponent(getId());
}
if(id.equalsIgnoreCase(getAddButtonId())) {
// Add a category to the list of selectable categories
// This is input for adding a category
HtmlInputText newCategoryInput = (HtmlInputText) comp.getParent().findComponent(getAddCategoryInputId());
String newCategoryName=newCategoryInput.getValue().toString();
CategoryBean.getInstance().addCategory(newCategoryName);
if(realCategories!=null){
realCategories.reset();
}
return;
}
else if (id.equalsIgnoreCase(getSaveButtonId())) {
realCategories.saveCategoriesSettings();
}
}
public String getEnabledCategories(IWContext iwc) {
StringBuffer categories = new StringBuffer(CategoryBean.CATEGORY_DELIMETER);
CategoryBean categoryBean = CategoryBean.getInstance();
String selectedCategory = null;
for (ContentCategory category: categoryBean.getCategories()) {
selectedCategory = iwc.getParameter(getCategoryKey(category));
if (!StringUtil.isEmpty(selectedCategory) && selectedCategory.equals(Boolean.TRUE.toString())) {
categories.append(category.getId()).append(CategoryBean.CATEGORY_DELIMETER);
}
}
return categories.toString();
}
private String getCategoryKey(ContentCategory category) {
String clearedKey = StringHandler.stripNonRomanCharacters(category.getId());
return new StringBuilder("contentcategory_").append(clearedKey).toString();
}
public void saveCategoriesSettings() {
if (this.resourcePath == null){
throw new RuntimeException("resourcePath is null");
}
IWContext iwc = CoreUtil.getIWContext();
// Save the selection of categories to the article
String categories = getEnabledCategories(iwc);
try {
WebDAVMetadataResource resource = (WebDAVMetadataResource) IBOLookup.getSessionInstance(iwc, WebDAVMetadataResource.class);
resource.setCategories(resourcePath, categories.toString(), getSetCategoriesOnParent());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
*/
@Override
public Object saveState(FacesContext ctx) {
Object values[] = new Object[7];
values[0] = super.saveState(ctx);
values[1] = this.resourcePath;
values[2] = Boolean.valueOf(this.setOnParent);
values[3] = Boolean.valueOf(this.displaySaveButton);
values[4] = this.setCategories;
values[5] = Boolean.valueOf(this.displayHeader);
values[6] = Boolean.valueOf(this.selectAnyCategory);
return values;
}
/**
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext,
* java.lang.Object)
*/
@Override
public void restoreState(FacesContext ctx, Object state) {
Object values[] = (Object[]) state;
super.restoreState(ctx, values[0]);
this.resourcePath = ((String) values[1]);
this.setOnParent = ((Boolean) values[2]).booleanValue();
this.displaySaveButton = ((Boolean) values[3]).booleanValue();
this.setCategories=(String)values[4];
this.displayHeader=((Boolean)values[5]).booleanValue();
this.selectAnyCategory = (Boolean) values[6];
}
@Override
public void encodeBegin(FacesContext context) throws IOException{
super.encodeBegin(context);
}
/**
* <p>
* Sets if the parent folder (of the current resource)should be set with the same category attributes as the current resource.
* </p>
* @param setOnParent
*/
public void setCategoriesOnParent(boolean setOnParent){
this.setOnParent=setOnParent;
}
public boolean getSetCategoriesOnParent(){
return this.setOnParent;
}
public void setDisplaySaveButton(boolean displaySave){
this.displaySaveButton=displaySave;
}
public boolean getDisplaySaveButton(){
return this.displaySaveButton;
}
/**
* <p>
* Set categories to preset with, this works only if resourcePath is not set.
* </p>
* @param setCategories
*/
public void setCategories(String setCategories) {
this.setCategories=setCategories;
}
public boolean isAddCategoryCreator() {
return addCategoryCreator;
}
public void setAddCategoryCreator(boolean addCategoryCreator) {
this.addCategoryCreator = addCategoryCreator;
}
public boolean isNeedDisplayCategoriesSelection(IWContext iwc) {
if (!areCategoriesFetched) {
getSelectedAndNotSelectedCategories(iwc);
}
return needDisplayCategoriesSelection;
}
public void getSelectedAndNotSelectedCategories(IWContext iwc) {
this.selectedCategories = new ArrayList<ContentCategory>();
this.notSelectedCategories = new ArrayList<ContentCategory>();
Locale locale = getLocale(iwc);
Collection<String> selectedCategories = null;
try {
selectedCategories = getSetCategoriesList();
} catch(Exception e) {
e.printStackTrace();
}
if (!ListUtil.isEmpty(selectedCategories)) {
ContentCategory category = null;
for (Iterator<String> selectedIter = selectedCategories.iterator(); selectedIter.hasNext();) {
String categoryKey = selectedIter.next();
category = CategoryBean.getInstance().getCategory(categoryKey);
if (category != null) {
if (category.getName(locale.toString()) != null && !category.isDisabled()) {
// Category exists for current locale and it's not disabled
this.selectedCategories.add(category);
}
}
}
}
List<String> providedCategoriesKeys = getProvidedCategoriesKeys();
Collection<ContentCategory> categories = CategoryBean.getInstance().getCategories(locale);
if (categories == null) {
localizedCategories = 0;
}
else {
localizedCategories = categories.size();
for (ContentCategory category : categories) {
if (!category.isDisabled() && (selectedCategories == null || !selectedCategories.contains(category.getId()))) {
if (providedCategoriesKeys != null && providedCategoriesKeys.contains(category.getId())) {
this.selectedCategories.add(category);
}
else {
this.notSelectedCategories.add(category);
}
}
}
}
if (this.selectedCategories.size() == 0 && this.notSelectedCategories.size() == 0) {
needDisplayCategoriesSelection = false;
}
else if (setCategories != null && this.selectedCategories.size() == 1) {
needDisplayCategoriesSelection = false; // If is set only one category, not showing categories editor
}
else {
needDisplayCategoriesSelection = true; // Showing categories to user
}
areCategoriesFetched = true;
}
private List<String> getProvidedCategoriesKeys() {
if (setCategories == null || setCategories.equals(CoreConstants.EMPTY) || setCategories.equals(CoreConstants.COMMA)) {
return null;
}
String[] keys = setCategories.split(CoreConstants.COMMA);
if (keys == null || keys.length == 0) {
return null;
}
return Arrays.asList(keys);
}
public int getLocalizedCategories() {
return localizedCategories;
}
public void setLocaleIdentity(String localeIdentity) {
this.localeIdentity = localeIdentity;
}
public boolean isSelectAnyCategory() {
return selectAnyCategory;
}
public void setSelectAnyCategory(boolean selectAnyCategory) {
this.selectAnyCategory = selectAnyCategory;
}
}