/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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.1 of
* the License, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.gatein.ui.admin.redirect.beans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.model.DevicePropertyCondition;
import org.exoplatform.portal.config.model.NodeMap;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.config.model.PortalRedirect;
import org.exoplatform.portal.config.model.RedirectCondition;
import org.exoplatform.portal.config.model.RedirectMappings;
import org.exoplatform.portal.config.model.UserAgentConditions;
import org.gatein.api.PortalRequest;
import org.gatein.api.navigation.Navigation;
import org.gatein.api.navigation.Node;
import org.gatein.api.navigation.Nodes;
import org.gatein.api.site.SiteId;
@ManagedBean(name = "rdrEdit")
@ViewScoped
public class EditRedirectBean implements Serializable {
private static final long serialVersionUID = 1L;
private boolean isEdit = false;
public boolean getIsEdit() {
return isEdit;
}
public void setIsEdit(boolean isEdit) {
this.isEdit = isEdit;
}
DataStorage ds = null;
PortalConfig cfg = null;
private void fetchDataStorage() {
// FIXME: Use webui Util.getUIPortal() ?
if (ds == null) {
ds = (DataStorage) ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(DataStorage.class);
}
}
protected PortalRedirect pr;
// So we keep a reference to redirects with updated name
protected String originalName;
protected String redirectName;
protected boolean enabled;
protected RedirectMappings mappings;
private boolean isNewRedirect;
/**
* Sets the name of the Redirect to be edited. It's _NOT_ used to change the current redirect name!
*/
public void configRedirect() {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
redirectName = params.get("rname");
}
public void addRedirect(String site) {
this.siteName = site;
this.pr = new PortalRedirect();
this.pr.setName(site + "_" + Long.toHexString(System.currentTimeMillis()));
this.originalName = pr.getName();
this.pr.setConditions(new ArrayList<RedirectCondition>());
RedirectMappings rm = new RedirectMappings();
rm.setMappings(new ArrayList<NodeMap>());
this.originNodeNames = loadOriginNodes(site);
this.redirectNodeNames = loadRedirectNodes();
this.pr.setMappings(rm);
this.mappings = pr.getMappings();
isNewRedirect = true;
}
/**
* Returns the name of the redirect being edited.
*
* @return
*/
public String getName() {
return this.pr != null ? this.pr.getName() : redirectName;
}
/**
* Returns the original name of the redirect being edited.
*
* @return
*/
public String getOriginalName() {
return originalName;
}
/**
* Sets the Redirect Name.
*
* @param name
*/
public void setName(String name) {
if (this.pr != null) {
this.pr.setName(name);
}
this.redirectName = name;
}
/**
* Toggles redirect enabled/disabled state. Persisted immediately, as it's used for the redirects listing.
*
* @param site the site the affected redirect belongs to
* @param name the name of the redirect to be enabled/disabled
*/
public void toggleEnabled(String site, String name) {
try {
fetchDataStorage();
cfg = ds.getPortalConfig(site);
for (PortalRedirect pr : cfg.getPortalRedirects()) {
if (pr.getName().equals(name)) {
pr.setEnabled(!pr.isEnabled());
ds.save(cfg);
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void toggleEnabled() {
toggleEnabled(siteName, redirectName);
}
String deleteSite = null;
String deleteRedirect = null;
public void setDeleteRedirect(String site, String redirect) {
this.deleteSite = site;
this.deleteRedirect = redirect;
}
public String deleteRedirect() {
try {
fetchDataStorage();
cfg = ds.getPortalConfig(deleteSite);
ArrayList<PortalRedirect> redirects = cfg.getPortalRedirects();
int index = -1;
for (int i = 0; i < redirects.size(); i++) {
if (redirects.get(i).getName().equals(deleteRedirect)) {
index = i;
break;
}
}
if (index != -1) {
redirects.remove(index);
cfg.setPortalRedirects(redirects);
ds.save(cfg);
} else {
// redirect was not found or deleted...
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* After editing a redirect, save/persist it.
*
* @return
*/
public String saveRedirect() {
try {
fetchDataStorage();
cfg = ds.getPortalConfig(siteName);
ArrayList<PortalRedirect> redirects = cfg.getPortalRedirects();
// FIXME: getPortalRedirects() should return empty list instead of null
if (redirects == null) {
redirects = new ArrayList<PortalRedirect>();
}
boolean save = false;
if (isNewRedirect) {
redirects.add(pr);
save = true;
} else {
int index = -1;
for (int i = 0; i < redirects.size(); i++) {
if (redirects.get(i).getName().equals(originalName)) {
index = i;
break;
}
}
if (index != -1) {
redirects.set(index, this.pr);
save = true;
}
}
if (save) {
cfg.setPortalRedirects(redirects);
ds.save(cfg);
isNewRedirect = false;
} else {
// redirect was not found or saved...
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* After editing a redirect, cancel it's changes. Method restores the redirect state, name, conditions, mappings, etc to
* it's backup state. TODO: Try to clone the entire redirect for backup.
*/
public void rollbackRedirect() {
isEdit = false;
}
// ----- REDIRECT ENABLED, NAME & SITE -----
/**
* Sets the enabled/disabled state of a redirect, in edit mode. As it is in edit mode, it is not persisted as in {
* {@link #toggleEnabled(String, String)}, since it can be canceled.
*
* @param enabled the value to set the enabled property
*/
public void setEnabled(boolean enabled) {
pr.setEnabled(enabled);
}
/**
* Getter for the redirect enabled property, indicating if the redirect is active or not.
*
* @return a boolean indicating the redirect enabled property
*/
public boolean getEnabled() {
return pr != null ? pr.isEnabled() : false;
}
public String getRedirectSite() {
return this.pr != null ? this.pr.getRedirectSite() : null;
}
public void setRedirectSite(String redirectSite) {
this.pr.setRedirectSite(redirectSite);
loadRedirectNodes();
}
// ----- CONDITIONS -----
public ArrayList<RedirectCondition> getConditions() {
return pr != null ? pr.getConditions() : new ArrayList<RedirectCondition>();
}
public void setConditions(ArrayList<RedirectCondition> conditions) {
pr.setConditions(conditions);
}
// current condition being edited
private int currentConditionIndex;
private RedirectCondition editedCondition;
private ArrayList<DevicePropertyConditionWrapper> deviceProperties;
private String backupConditionName;
private ArrayList<String> backupContains;
private ArrayList<String> backupDoesNotContain;
private boolean isNewCondition = false;
private String siteName;
// holds selected node mapping site option
private String nodesSiteName;
// holds origin node names
private List<String> originNodeNames = new ArrayList<String>();
// holds redirect node names
private List<String> redirectNodeNames = new ArrayList<String>();
// copy of either origin or redirect node names, depending on selection
private List<String> currentNodeNames = new ArrayList<String>();
public int getCurrentConditionIndex() {
return currentConditionIndex;
}
public void setCurrentConditionIndex(int currentConditionIndex) {
this.currentConditionIndex = currentConditionIndex;
}
public RedirectCondition getEditedCondition() {
return editedCondition;
}
public void setEditedCondition(RedirectCondition editedCondition) {
this.editedCondition = editedCondition;
this.backupConditionName = editedCondition.getName();
this.backupContains = new ArrayList<String>(editedCondition.getUserAgentConditions().getContains());
this.backupDoesNotContain = new ArrayList<String>(editedCondition.getUserAgentConditions().getDoesNotContain());
// Since we don't use the DeviceProperties directly but a wrapper, we create it at this point
this.deviceProperties = new ArrayList<DevicePropertyConditionWrapper>();
if (editedCondition.getDeviceProperties() != null) {
for (DevicePropertyCondition prop : editedCondition.getDeviceProperties()) {
DevicePropertyCondition newProp = new DevicePropertyCondition();
newProp.setPropertyName(prop.getPropertyName());
newProp.setEquals(prop.getEquals());
newProp.setMatches(prop.getMatches());
newProp.setLessThan(prop.getLessThan());
newProp.setGreaterThan(prop.getGreaterThan());
this.deviceProperties.add(new DevicePropertyConditionWrapper(newProp));
}
}
}
public void addCondition() {
this.editedCondition = createNewCondition();
isNewCondition = true;
}
/**
* Removes a Redirect Condition entry from the edited redirect.
*
* @param index the index of the entry to remove
*/
public void removeCondition(Integer index) {
RedirectCondition rc = pr.getConditions().remove((int) index);
}
/**
* Creates a new redirect condition, sanitizing the initial values, as they are set to null instead of empty ArrayLists,
* etc.
*
* @return
*/
private RedirectCondition createNewCondition() {
RedirectCondition newRC = new RedirectCondition();
newRC.setName(this.siteName + "_" + redirectName +"_condition" + (pr.getConditions().size()+1));
newRC.setDeviceProperties(new ArrayList<DevicePropertyCondition>());
UserAgentConditions newUAC = new UserAgentConditions();
ArrayList<String> emptyContains = new ArrayList<String>();
emptyContains.add("");
newUAC.setContains(emptyContains);
ArrayList<String> emptyDoesNotContain = new ArrayList<String>();
emptyDoesNotContain.add("");
newUAC.setDoesNotContain(emptyDoesNotContain);
newRC.setUserAgentConditions(newUAC);
deviceProperties = new ArrayList<DevicePropertyConditionWrapper>();
return newRC;
}
/**
* Adds a new "CONTAINS" entry to the edited condition.
*/
public void addContains() {
editedCondition.getUserAgentConditions().getContains().add("");
}
/**
* Removes a "CONTAINS" entry from the edited condition.
*
* @param index the index of the entry to remove
*/
public void removeContains(Integer index) {
String rc = editedCondition.getUserAgentConditions().getContains().remove((int) index);
}
/**
* Adds a new "DOES NOT CONTAIN" entry to the edited condition.
*/
public void addDoesNotContain() {
editedCondition.getUserAgentConditions().getDoesNotContain().add("");
}
/**
* Removes a "DOES NOT CONTAIN" entry from the edited condition.
*
* @param index the index of the entry to remove
*/
public void removeDoesNotContain(Integer index) {
String rc = editedCondition.getUserAgentConditions().getDoesNotContain().remove((int) index);
}
/**
* After editing a condition, save it. Method does nothing, as all changes should be already present in the object.
*
* @return
*/
public String saveCondition() {
// remove all empty entries from User Agent Conditions
editedCondition.getUserAgentConditions().getContains().removeAll(Collections.singleton(""));
editedCondition.getUserAgentConditions().getDoesNotContain().removeAll(Collections.singleton(""));
if (isNewCondition) {
this.pr.getConditions().add(editedCondition);
isNewCondition = false;
}
// We don't use DevicePropertyCondition directly, but a wrapper. Need to convert back.
ArrayList<DevicePropertyCondition> dpcs = new ArrayList<DevicePropertyCondition>();
for(DevicePropertyConditionWrapper dpcw : deviceProperties) {
dpcs.add(dpcw.getDevicePropertyCondition());
}
this.editedCondition.setDeviceProperties(dpcs);
return null;
}
/**
* After editing a condition, cancel it's changes. Method restores the conditions, properties, etc to it's backup state.
* TODO: Try to clone the entire condition for backup.
*/
public void rollbackCondition() {
if (!isNewCondition) {
this.editedCondition.setName(backupConditionName);
this.editedCondition.getUserAgentConditions().setContains(backupContains);
this.editedCondition.getUserAgentConditions().setDoesNotContain(backupDoesNotContain);
/* GTNPORTAL-XXXX: We don't use DevicePropertyCondition directly, no need to rollback
ArrayList<DevicePropertyCondition> dpcs = new ArrayList<DevicePropertyCondition>();
for(DevicePropertyConditionWrapper dpcw : backupDeviceProperties) {
dpcs.add(dpcw.getDevicePropertyCondition());
}
this.editedCondition.setDeviceProperties(dpcs);
*/
}
}
// ----- PROPERTIES -----
/**
* Adds a new Device Property to the edited condition.
*/
public void addProperty() {
if (editedCondition.getDeviceProperties() == null) {
editedCondition.setDeviceProperties(new ArrayList<DevicePropertyCondition>());
}
DevicePropertyCondition dpc = new DevicePropertyCondition();
// FIXME: Workaround for GTNPORTAL-3073, remove when not needed
dpc.setEquals(null);
dpc.setGreaterThan(null);
dpc.setLessThan(null);
dpc.setMatches(null);
deviceProperties.add(new DevicePropertyConditionWrapper(dpc));
}
/**
* Removes a Device Property entry from the edited condition.
*
* @param index the index of the entry to remove
*/
public void removeProperty(Integer index) {
/*DevicePropertyConditionWrapper rc = */this.deviceProperties.remove((int) index);
}
// Use Device Property Wrapper
public ArrayList<DevicePropertyConditionWrapper> getDeviceProperties() {
return this.deviceProperties;
}
public void setDeviceProperties(ArrayList<DevicePropertyConditionWrapper> dpcws) {
this.deviceProperties = dpcws;
}
// ----- MAPPINGS -----
public void addNodeMapping() {
this.pr.getMappings().getMappings().add(0, new NodeMap());
}
public void removeNodeMapping(int index) {
ArrayList<NodeMap> mappings = this.pr.getMappings().getMappings();
mappings.remove(index);
this.pr.getMappings().setMappings(mappings);
}
public boolean getUseNodeNameMatching() {
return (this.pr != null && this.pr.getMappings() != null) ? this.pr.getMappings().isUseNodeNameMatching() : false;
}
public void setUseNodeNameMatching(boolean useNodeNameMatching) {
this.pr.getMappings().setUseNodeNameMatching(useNodeNameMatching);
}
public RedirectMappings getMappings() {
return mappings;
}
public void setMappings(RedirectMappings mappings) {
this.mappings = mappings;
}
/**
* Returns the list of Portal nodes for the origin.
*
* @return a List of Strings representing node paths
*/
public List<String> getOriginNodeNames() {
return this.originNodeNames;
}
/**
* Returns the list of Portal nodes for the redirect.
*
* @return a List of Strings representing node paths
*/
public List<String> getRedirectNodeNames() {
return this.redirectNodeNames;
}
/**
* Returns the name of the Portal site for the selected option (origin or redirect) by {@link #setCurrentNodeNames(boolean)}
* .
*
* @return
*/
public String getCurrentNodesSiteName() {
return nodesSiteName;
}
/**
* Returns the list of Portal nodes for the selected option (origin or redirect) by {@link #setCurrentNodeNames(boolean)}.
*
* @return
*/
public List<String> getCurrentNodeNames() {
return currentNodeNames;
}
public void setCurrentNodeNames(boolean isOrigin) {
if (isOrigin) {
this.currentNodeNames = originNodeNames;
this.nodesSiteName = siteName;
} else {
this.currentNodeNames = redirectNodeNames;
this.nodesSiteName = this.pr.getRedirectSite();
}
}
// --- Utilities ----------------------------------------------------------
public void load(String site, String redirect) {
isNewRedirect = false;
this.siteName = site;
fetchDataStorage();
try {
cfg = ds.getPortalConfig(site);
for (PortalRedirect pr : cfg.getPortalRedirects()) {
if (pr.getName().equals(redirect)) {
this.pr = pr;
this.redirectName = pr.getName();
this.originalName = pr.getName();
this.enabled = pr.isEnabled();
this.mappings = pr.getMappings();
this.originNodeNames = loadOriginNodes(site);
this.redirectNodeNames = loadRedirectNodes();
isEdit = true;
return;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean checkSiteExists(String name) {
if (name != null) {
Navigation nav = PortalRequest.getInstance().getPortal().getNavigation(new SiteId(name));
return nav != null;
}
return false;
}
// TODO: move this to a different bean
public List<String> loadOriginNodes(String siteName) {
try {
ArrayList<String> nodes = new ArrayList<String>();
if (siteName != null) {
Node n = PortalRequest.getInstance().getPortal().getNavigation(new SiteId(siteName))
.getRootNode(Nodes.visitAll());
for (Node node : Nodes.asList(n)) {
nodes.add(node.getNodePath().toString());
}
}
return nodes;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public List<String> loadRedirectNodes() {
try {
ArrayList<String> nodes = new ArrayList<String>();
if (this.pr.getRedirectSite() != null) {
Navigation nav = PortalRequest.getInstance().getPortal().getNavigation(new SiteId(this.pr.getRedirectSite()));
if (nav != null) {
Node n = nav.getRootNode(Nodes.visitAll());
for (Node node : Nodes.asList(n)) {
nodes.add(node.getNodePath().toString());
}
}
}
this.redirectNodeNames = nodes;
return nodes;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// sortable
private int sortFrom = -1;
private int sortTo = -1;
private String sortSite = null;
public int getSortFrom() {
return sortFrom;
}
public void setSortFrom(int sortFrom) {
this.sortFrom = sortFrom;
}
public int getSortTo() {
return sortTo;
}
public void setSortTo(int sortTo) {
this.sortTo = sortTo;
}
public String getSortSite() {
return sortSite;
}
public void setSortSite(String sortSite) {
this.sortSite = sortSite;
}
public void doSortCondition() {
ArrayList<RedirectCondition> conds = pr.getConditions();
conds.add(sortTo, conds.remove(sortFrom));
}
public void doSortRedirect() {
fetchDataStorage();
try {
cfg = ds.getPortalConfig(sortSite);
ArrayList<PortalRedirect> redirects = cfg.getPortalRedirects();
redirects.add(sortTo, redirects.remove(sortFrom));
ds.save(cfg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}