package org.openedit.data;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.openedit.Data;
import org.openedit.profile.UserProfile;
import org.openedit.xml.XmlArchive;
import org.openedit.xml.XmlFile;
import com.openedit.OpenEditException;
import com.openedit.OpenEditRuntimeException;
import com.openedit.page.Page;
import com.openedit.page.manage.PageManager;
import com.openedit.page.manage.TextLabelManager;
import com.openedit.users.User;
import com.openedit.util.PathUtilities;
public class PropertyDetailsArchive {
private static final Log log = LogFactory
.getLog(PropertyDetailsArchive.class);
protected XmlArchive fieldXmlArchive;
protected String fieldCatalogId;
protected Map fieldViewLabels;
protected TextLabelManager fieldTextLabelManager;
protected PageManager fieldPageManager;
protected SearcherManager fieldSearcherManager;
protected Map<String, View> fieldViewCache;
protected Map fieldPropertyDetails;
public SearcherManager getSearcherManager() {
return fieldSearcherManager;
}
public void setSearcherManager(SearcherManager inSearcherManager) {
fieldSearcherManager = inSearcherManager;
}
public PageManager getPageManager() {
return fieldPageManager;
}
public void setPageManager(PageManager inPageManager) {
fieldPageManager = inPageManager;
}
public TextLabelManager getTextLabelManager() {
return fieldTextLabelManager;
}
public void setTextLabelManager(TextLabelManager inTextLabelManager) {
fieldTextLabelManager = inTextLabelManager;
}
public List getDataProperties(String inType) {
PropertyDetails details = getPropertyDetails(inType);
if (details == null) {
return Collections.EMPTY_LIST;
}
return details.getDetails();
}
public List getIndexProperties(String inType) {
PropertyDetails details = getPropertyDetails(inType);
if (details == null) {
return Collections.EMPTY_LIST;
}
return details.findIndexProperties();
}
public List getStoredProperties(String inType) {
PropertyDetails details = getPropertyDetails(inType);
if (details == null) {
return Collections.EMPTY_LIST;
}
return details.findStoredProperties();
}
public String getConfigurationPath(String inPath) {
String path = "/WEB-INF/data/" + getCatalogId() + inPath;
if (!getPageManager().getRepository().doesExist(path)) {
path = "/" + getCatalogId() + "/data" + inPath;
// if (!getPageManager().getPage(path).exists())
// {
// /*
// // now check the extensions
// if (!(path.contains("dataextensions") ||
// path.contains("translation")))
// {
// HitTracker hits = getSearcherManager().getList(getCatalogId(),
// "dataextensions");
// for (Iterator iterator = hits.iterator(); iterator.hasNext();)
// {
// Data hit = (Data) iterator.next();
// String catalogid = hit.get("catalogid");
// String remotepath = "/" + catalogid + "/data/" + inPath;
// if (getPageManager().getPage(remotepath).exists())
// {
// return remotepath;
// }
// }
// }
// */
// // legacy support
// if (inPath.startsWith("/fields/"))
// {
// inPath = inPath.replace(".xml", "properties.xml");
// inPath = inPath.replace("/fields/", "/");
// }
// path = "/" + getCatalogId() + "/configuration" + inPath;
//
// }
}
return path;
}
/**
* This returns a subset of the list of Detail's as found in
* store/configuration/{inType}.xml The subset is determined by
* inSubsetProperties.
*
* @param inType
* The type of data (i.e., product, catalog, item, order, etc...)
* @param inView
* Identifies the file to look in for the subset of properties to
* take from those found in inType. The file is
* store/configuration/fields/properties{inSubsetProperties}.xml
* @param inUser
* @return A List of Details
* @deprecated
*/
public List getDataProperties(String inType, String inView, User inUser) {
PropertyDetails propdetails = getPropertyDetailsCached(inType);
if (propdetails == null) {
log.error("No such properties file " + inType);
return null;
}
return getDetails(propdetails, inView, inUser);
}
public List getDataProperties(String inType, String inView,
UserProfile inProfile) {
PropertyDetails propdetails = getPropertyDetailsCached(inType);
if (propdetails == null) {
log.error("No such properties file " + inType);
return null;
}
return getDetails(propdetails, inView, inProfile);
}
public boolean viewExists(String inView) {
XmlFile file = getViewXml(inView);
return file.isExist();
}
protected XmlFile getViewXml(String inView) {
String path = getConfigurationPath("/views/" + inView + ".xml");
XmlFile file = getXmlArchive().getXml(path);
return file;
}
public View getView(String inSearchType, String inView,
UserProfile inProfile) {
PropertyDetails details = getPropertyDetailsCached(inSearchType);
View view = getView(details, inView, inProfile);
return view;
}
/**
* @deprecated use getView(
*/
public View getDetails(PropertyDetails propdetails, String inView,
User inUser) {
return getView(propdetails, inView, (UserProfile) null);
}
/**
* @deprecated use getView(
*/
public View getDetails(PropertyDetails propdetails, String inView,
UserProfile inProfile) {
return getView(propdetails, inView, inProfile);
}
public View getView(PropertyDetails propdetails, String inView,
UserProfile inProfile) {
String id = inView;
Collection values = null;
if (inProfile != null) // this is important since they may have created
// a custom search screen or something
{
id = id + "_" + inProfile.get("settingsgroup");
String propId = "view_" + inView.replace('/', '_');
values = inProfile.getValues(propId);
if (values != null) {
id = id + "_" + values.toString(); // More specific to the user,
// 1000 limit cache
}
}
View view = null;
if (id != null) {
view = getViewCache().get(id);
}
if (view != null) {
return view;
}
XmlFile types = getViewXml(inView);
if (types.isExist()) {
view = readViewElement(propdetails, types.getRoot(), inView);
if (view != null) {
view.setViewFile(types);
}
}
if(view == null){
view = new View();
view.setId(inView);
}
if (inProfile != null) {
// Support custom values such as columns or searches
if (values != null) {
// filter out any that are not in the user values
List existing = new ArrayList(view);
for (Iterator iterator = existing.iterator(); iterator
.hasNext();) {
PropertyDetail detail = (PropertyDetail) iterator
.next();
if (values.size() > 0 && !values.contains(detail)) {
view.remove(detail);
}
}
// add new columns
for (Iterator iterator = values.iterator(); iterator
.hasNext();) {
String vid = (String) iterator.next();
if (vid.length() > 0 && view.findDetail(id) == null) {
PropertyDetail detail = loadDetail(propdetails,
types, inView, vid);
if (detail != null) {
view.add(detail);
}
}
}
}
}
if(view.size() == 0){
return null;
}
if (getViewCache().size() > 1000) {
getViewCache().clear();
}
getViewCache().put(id, view);
return view;
}
// public PropertyDetail getDetail(PropertyDetails propdetails, String
// inView, String inFieldName, User inUser)
// {
// View viewdetails = getDetails(propdetails, inView, inUser);
// }
protected PropertyDetail loadDetail(PropertyDetails propdetails,
XmlFile inViewData, String inView, String inFieldName) {
// String level = null;//
// if (inUser != null)
// {
// String level = (String) inUser.getProperty("datalevel");
// }
// XmlFile types = null;
// if (level != null)
// {
// String path = getConfigurationPath("/views/" + inView + level +
// ".xml");
// types = getXmlArchive().getXml(path);
// }
// if (types == null || !types.isExist())
// {
// String path = getConfigurationPath("/views/" + inView + ".xml");
// types = getXmlArchive().getXml(path);
// }
PropertyDetail detail = propdetails.getDetail(inFieldName);
if (inViewData.isExist()) {
if (detail != null) {
Element child = inViewData.getElementById(inFieldName);
if (child != null) {
PropertyDetail local = detail.copy();
local.setView(inView);
local.setCatalogId(getCatalogId());
// local.setSearchType(getS)
populateViewElements(child, local);
return local;
}
}
}
return detail;
}
public XmlArchive getXmlArchive() {
return fieldXmlArchive;
}
public void setXmlArchive(XmlArchive inXmlArchive) {
fieldXmlArchive = inXmlArchive;
}
protected Map getPropertyDetails() {
if (fieldPropertyDetails == null) {
fieldPropertyDetails = new HashMap();
}
return fieldPropertyDetails;
}
/**
* This returns the properties found in store/configuration/{inType}.xml. In
* other words, all the possible properties for that type.
*
* @param The
* type of data (i.e., product, catalog, item, order, etc...)
* @return PropertyDetails
*/
public PropertyDetails getPropertyDetails(String inType) {
PropertyDetails details = (PropertyDetails) getPropertyDetails().get(
inType);
try {
String path = getConfigurationPath("/fields/" + inType + ".xml");
XmlFile settings = getXmlArchive().loadXmlFile(path); // checks time
// stamp.
// returns
// null if
// changed
if (details != null && details.getInputFile() == settings) {
return details;
}
log.info("Loading " + getCatalogId() + " " + inType);
settings = getXmlArchive().getXml(path);
if (!settings.isExist() && !path.contains("dataextensions")) {
if (inType.endsWith("Log")) {
path = getConfigurationPath("/fields/defaultLog.xml");
} else {
path = getConfigurationPath("/fields/default.xml");
}
// This should not happen as well
settings = getXmlArchive().getXml(path);
}
details = new PropertyDetails();
if (settings.isExist()) {
setAllDetails(details, inType, settings.getRoot());
getViewLabels().clear();
}
// load any defaults - AFTER we have loaded all the existing stuff.
// don't overwrite anything that is here already.
List paths = getPageManager()
.getChildrenPaths(
"/" + getCatalogId() + "/data/fields/" + inType
+ "/", true);
for (Iterator iterator = paths.iterator(); iterator.hasNext();) {
String defaultfile = (String) iterator.next();
if (defaultfile.endsWith(".xml")) {
XmlFile defaults = getXmlArchive().loadXmlFile(defaultfile);
PropertyDetails extras = new PropertyDetails();
setAllDetails(extras, inType, defaults.getRoot());
for (Iterator iterator2 = extras.iterator(); iterator2
.hasNext();) {
PropertyDetail detail = (PropertyDetail) iterator2
.next();
PropertyDetail existing = details.getDetail(detail
.getId());
if (existing == null) {
details.addDetail(detail);
}
}
}
}
details.setInputFile(settings);
getPropertyDetails().put(inType, details);
return details;
} catch (OpenEditException ex) {
throw new OpenEditRuntimeException(ex);
}
}
public PropertyDetails getPropertyDetailsCached(String inType) {
PropertyDetails details = (PropertyDetails) getPropertyDetails().get(
inType);
if (details == null) {
return getPropertyDetails(inType);
}
return details;
}
public void savePropertyDetails(PropertyDetails inDetails, String inType,
User inUser) {
XmlFile file = new XmlFile();
String path = "/WEB-INF/data/" + getCatalogId() + "/fields/" + inType
+ ".xml";
file.setPath(path);
Element root = DocumentHelper.createElement("properties");
if (inDetails.getPrefix() != null) {
root.addAttribute("prefix", inDetails.getPrefix());
}
if (inDetails.getClassName() != null) {
root.addAttribute("class", inDetails.getClassName());
}
if (inDetails.getBeanName() != null) {
root.addAttribute("beanname", inDetails.getBeanName());
}
file.setRoot(root);
file.setElementName("property");
for (Iterator iterator = inDetails.getDetails().iterator(); iterator
.hasNext();) {
PropertyDetail detail = (PropertyDetail) iterator.next();
Element element = file.addNewElement();
fillElement(inDetails.getDefaults(), element, detail);
}
getXmlArchive().saveXml(file, inUser);
clearCache();
}
protected Map<String, View> getViewCache() {
if (fieldViewCache == null) {
fieldViewCache = new HashMap<String, View>();
}
return fieldViewCache;
}
public void clearCache() {
getPropertyDetails().clear();
getViewCache().clear();
getViewLabels().clear();
}
public void savePropertyDetails(PropertyDetails inDetails, String inType,
User inUser, String path) {
XmlFile file = new XmlFile();
file.setPath(path);
Element root = DocumentHelper.createElement("properties");
if (inDetails.getPrefix() != null) {
root.addAttribute("prefix", inDetails.getPrefix());
}
file.setRoot(root);
file.setElementName("property");
for (Iterator iterator = inDetails.getDetails().iterator(); iterator
.hasNext();) {
PropertyDetail detail = (PropertyDetail) iterator.next();
Element element = file.addNewElement();
fillElement(inDetails.getDefaults(), element, detail);
}
getXmlArchive().saveXml(file, inUser);
clearCache();
}
public String getCatalogId() {
return fieldCatalogId;
}
public void setCatalogId(String inCatalogId) {
fieldCatalogId = inCatalogId;
}
public PropertyDetail getDataProperty(String inType, String inView,
String inField, User inUser) {
PropertyDetails details = getPropertyDetailsCached(inType);
if (details == null) {
return null;
}
View dataprops = getDetails(details, inView, inUser);
if (dataprops != null) {
return dataprops.findDetail(inField);
}
return null;
}
public void setAllDetails(PropertyDetails details, String inType,
Element root) {
List newdetails = new ArrayList();
Map defaults = new HashMap();
for (Iterator iterator = root.attributeIterator(); iterator.hasNext();) {
Attribute attr = (Attribute) iterator.next();
String name = attr.getName();
String value = attr.getValue();
defaults.put(name, value);
}
details.setDefaults(defaults);
for (Iterator iter = root.elementIterator("property"); iter.hasNext();) {
Element element = (Element) iter.next();
PropertyDetail d = createDetail(defaults, element, inType);
newdetails.add(d);
}
// Collections.sort(newdetails);
details.setDetails(newdetails);
}
public void fillElement(Map defaults, Element element,
PropertyDetail inDetail) {
element.addAttribute("id", inDetail.getId());
element.addAttribute("externalid", inDetail.getExternalId());
element.addAttribute("externaltype", inDetail.getExternalType());
if (inDetail.getCatalogId() != null
&& !inDetail.getCatalogId().equals(getCatalogId())) {
element.addAttribute("catalogid", inDetail.getCatalogId());
}
if (inDetail.getText() != null) {
element.setText(inDetail.getText());
}
if (inDetail.isIndex())
element.addAttribute("index", "true");
if (inDetail.isKeyword())
element.addAttribute("keyword", "true");
if (inDetail.isFilter())
element.addAttribute("filter", "true");
if (inDetail.isStored())
element.addAttribute("stored", "true");
if (inDetail.isEditable())
element.addAttribute("editable", "true");
if (inDetail.isSortable())
element.addAttribute("sortable", "true");
String type = inDetail.getDataType();
if (type != null) {
element.addAttribute("type", type);
}
String viewtype = inDetail.getViewType();
if (viewtype != null) {
element.addAttribute("viewtype", viewtype);
}
for (Iterator iterator = inDetail.getProperties().keySet().iterator(); iterator
.hasNext();) {
String key = (String) iterator.next();
String val = (String) inDetail.getProperties().get(key);
if (!val.equals(defaults.get(key))) {
element.addAttribute(key, val);
}
}
}
protected void populateViewElements(Element inElement,
PropertyDetail inDetail) {
String label = inElement.getTextTrim();
if (label != null && label.length() > 0) {
inDetail.setText(label);
}
// Set all the remaining attributes as properties
for (Iterator iterator = inElement.attributeIterator(); iterator
.hasNext();) {
Attribute attr = (Attribute) iterator.next();
String name = attr.getName();
String value = attr.getValue();
inDetail.setProperty(name, value);
// log.info("Read" + name + " " + value);
}
}
protected PropertyDetail createDetail(Map defaults, Element element,
String inType) {
PropertyDetail d = new PropertyDetail();
d.setTextLabelManager(getTextLabelManager());
for (Iterator iterator = defaults.keySet().iterator(); iterator
.hasNext();) {
String key = (String) iterator.next();
String value = (String) defaults.get(key);
d.setProperty(key, value);
}
String type = element.attributeValue("type");
d.setDataType(type);
populateViewElements(element, d);
if (d.getCatalogId() == null) {
d.setCatalogId(fieldCatalogId);
}
if (d.getSearchType() == null) {
d.setSearchType(inType);
}
if (d.isViewType("list") && d.getListId() == null) {
d.setListId(d.getId());
}
return d;
}
protected List listFilesByFolderType(String inFolderType,
boolean includeExtensions) {
// lists, views, fields
List datapaths = getPageManager().getChildrenPaths(
"/WEB-INF/data/" + getCatalogId() + "/" + inFolderType);
String inPath = "/" + getCatalogId() + "/data/" + inFolderType + "/";
List basepaths = getPageManager().getChildrenPaths(inPath, true);
Set set = new HashSet();
for (Iterator iterator = basepaths.iterator(); iterator.hasNext();) {
String path = (String) iterator.next();
path = PathUtilities.extractPageName(path);
if (!path.startsWith("_")) {
set.add(path);
}
}
for (Iterator iterator = datapaths.iterator(); iterator.hasNext();) {
String path = (String) iterator.next();
path = PathUtilities.extractPageName(path);
if (!path.startsWith("_")) {
set.add(path);
}
}
// // We don't want this in a loop or to follow a chain.
List sorted = new ArrayList(set);
// if (includeExtensions)
// {
// HitTracker extensions = (HitTracker)
// getSearcherManager().getList(getCatalogId(), "dataextensions");
//
// for (Iterator iterator = extensions.iterator(); iterator.hasNext();)
// {
// Data remotecatalog = (Data) iterator.next();
// String catalogid = remotecatalog.get("catalogid");
// PropertyDetailsArchive archive =
// getSearcherManager().getPropertyDetailsArchive(catalogid);
// List remotevalues = archive.listFilesByFolderType(inFolderType,
// false);
// sorted.addAll(remotevalues);
// }
// }
Collections.sort(sorted);
return sorted;
}
public List listSearchTypes() {
List fields = listFilesByFolderType("fields", true);
HashSet all = new HashSet(fields);
List lists = listFilesByFolderType("lists", true);
all.addAll(lists);
List sorted = new ArrayList(all);
Collections.sort(sorted);
return sorted;
}
public List listViewTypes() {
return listFilesByFolderType("views/", true);
}
public List listViews(String inViewType) {
return listFilesByFolderType("views/" + inViewType, true);
}
public Data getView(String inType, String inView) {
// Guess the type is not used. the inview has the type in the path name?
return getViewXml(inView);
}
public String getViewLabel(String inView) {
String usage = (String) getViewLabels().get(inView);
if (usage == null) {
Data view = getViewXml(inView);
usage = view.get("usagelabel");
if (usage == null) {
usage = "";
}
getViewLabels().put(inView, usage);
}
return usage;
}
protected Map getViewLabels() {
if (fieldViewLabels == null) {
fieldViewLabels = new HashMap();
}
return fieldViewLabels;
}
public View readViewElement(PropertyDetails inDetails, Element inElem,
String inViewName) {
View view = new View();
view.setId(inViewName);
for (Iterator iter = inElem.elementIterator(); iter.hasNext();) {
Element elem = (Element) iter.next();
if (elem.getName().equals("section")) {
View child = readViewElement(inDetails, elem, inViewName);
if (child != null) {
child.setTitle(elem.attributeValue("title"));
view.add(child);
}
} else if (elem.getName().equals("property")) {
String key = elem.attributeValue("id");
PropertyDetail detail = inDetails.getDetail(key);
if (detail != null) {
PropertyDetail local = detail.copy();
local.setView(inViewName);
populateViewElements(elem, local);
view.add(local);
}
}
}
return view;
}
public void saveView(String inCatalogId, View inView, User inUser) {
XmlFile file = getXmlArchive().getXml(
"/WEB-INF/data/" + inCatalogId + "/views/" + inView.getId()
+ ".xml");
file.clear();
Element root = file.getRoot();
appendValues(root, inView);
getXmlArchive().saveXml(file, inUser);
clearCache();
}
protected void appendValues(Element inRoot, View inView) {
for (Iterator iterator = inView.iterator(); iterator.hasNext();) {
Object object = (Object) iterator.next();
if (object instanceof PropertyDetail) {
Element child = inRoot.addElement("property");
PropertyDetail prop = (PropertyDetail) object;
child.addAttribute("id", prop.getId());
} else if (object instanceof View) {
Element child = inRoot.addElement("section");
View view = (View) object;
child.addAttribute("title", view.getTitle());
appendValues(child, view);
}
}
}
/**
* This is cached
*
* @param inSearchType
* @param inView
* @param inPropertyid
* @param inUserProfile
* @return
*/
public PropertyDetail getDetail(String inSearchType, String inView,
String inPropertyid, UserProfile inUserProfile) {
PropertyDetail detail = null;
if (inView == null) {
PropertyDetails details = getPropertyDetailsCached(inSearchType);
detail = details.getDetail(inPropertyid);
return detail;
}
View view = getView(inSearchType, inView, inUserProfile);
if (view != null) {
detail = view.findDetail(inPropertyid);
} else {
PropertyDetails details = getPropertyDetailsCached(inSearchType);
detail = details.getDetail(inPropertyid);
}
return detail;
}
public void clearCustomSettings(String inSearchType)
{
String path = getConfigurationPath("/fields/" + inSearchType + ".xml");
Page found = getPageManager().getPage(path);
getPageManager().removePage(found);
getPropertyDetails().remove(inSearchType);
}
public void reloadSettings(String inSearchType)
{
getPropertyDetails().remove(inSearchType);
}
}