/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.wgpublisher.hdb;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import de.bannkreis.groq.Groq;
import de.innovationgate.utils.MD5HashingInputStream;
import de.innovationgate.utils.UIDGenerator;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGAbstractResultSet;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDesignChangeEvent;
import de.innovationgate.webgate.api.WGDesignChangeListener;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGDocumentKey;
import de.innovationgate.webgate.api.WGFileContainer;
import de.innovationgate.webgate.api.WGHierarchicalDatabase;
import de.innovationgate.webgate.api.WGRelationData;
import de.innovationgate.webgate.api.WGResultSet;
import de.innovationgate.webgate.api.utils.MasterSessionTask;
import de.innovationgate.wgpublisher.ManagedDBAttribute;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.expressions.ExpressionEngine;
import de.innovationgate.wgpublisher.expressions.ExpressionEngineFactory;
import de.innovationgate.wgpublisher.expressions.ExpressionResult;
import de.innovationgate.wgpublisher.expressions.tmlscript.TMLScriptGlobal;
import de.innovationgate.wgpublisher.webtml.Query;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;
import de.innovationgate.wgpublisher.webtml.utils.UniqueNamePartFormatter;
public class HDBModel implements ManagedDBAttribute, WGDesignChangeListener {
public static final Logger LOG = Logger.getLogger("wga.hdbmodel");
public static final String HDBMODEL_GLOBAL = "HDBModel";
public static final String ITEM_TYPE = "$HDBModel_type";
public static final String TYPE_STORAGE = "storage";
public static final String TYPE_CONTENT = "content";
private static final Object ELEMENT_STORAGE = "storage";
private static final Object ELEMENT_CONTENT = "content";
public static final String MODEL_FILE = "hdb-model.xml";
private static final String SYSTEMFC_DOCKEY = (new WGDocumentKey(WGDocument.TYPE_FILECONTAINER, "system", null)).toString();
public static final String ITEM_ID = "$HDBModel_contentid";
public static final String ITEM_STORAGE_ID = "$HDBModel_storageid";
private static final String EXTDATA_MODEL_HASH = "hdbmodel_defhash";
private Document _definition;
private long _definitionTime;
private WGDatabase _db;
private WGHierarchicalDatabase _hdb;
private WGACore _core;
private String _definitionHash;
private boolean _modelVersionChanged = false;
public WGACore getCore() {
return _core;
}
public HDBModel(WGACore core, WGDatabase db, WGFileContainer model) throws DocumentException, WGAPIException, NoSuchAlgorithmException, IOException {
_core = core;
_db = db;
_db.addDesignChangeListener(this);
_hdb = WGHierarchicalDatabase.getInstance(_db.getDbReference());
readDefinition(model);
String oldHash = null;
if (_db.getContentStoreVersion() >= WGDatabase.CSVERSION_WGA5) {
if (_db.getExtensionDataNames().contains(EXTDATA_MODEL_HASH)) {
oldHash = (String) db.getExtensionData(EXTDATA_MODEL_HASH);
}
}
else {
LOG.warn("Please use HDB model with a OpenWGA content store of version 5 or higher to enable all model features.");
}
if (oldHash != null && !oldHash.equals(_definitionHash) && !"false".equals(System.getProperty("de.innovationgate.wga.hdbmodel.reinit"))) {
LOG.info("HDB model changed. Performing complete model reinitialisation.");
_modelVersionChanged = true;
}
Iterator children = _definition.getRootElement().elements().iterator();
while (children.hasNext()) {
Element child = (Element) children.next();
initModel(child, null);
}
if (_modelVersionChanged || oldHash == null) {
db.writeExtensionData(EXTDATA_MODEL_HASH, _definitionHash);
_modelVersionChanged = false;
}
}
private void initModel(Element modelNode, WGContent parent) throws WGAPIException {
Iterator children;
WGContent document;
if (modelNode.getName().equals("storage")) {
if (parent != null) {
if (_hdb.isStorage(parent)) {
document = _hdb.getOrCreateStorage(parent, modelNode.attributeValue("sid"));
}
else {
HDBModelParams params = new HDBModelParams(TYPE_STORAGE);
document = _hdb.getOrCreateUIDContent(parent, modelNode.attributeValue("sid"), params);
}
}
else {
document = _hdb.getOrCreateStorage(modelNode.attributeValue("sid"));
}
// If the store does not yet have a type item we regard it as just created an initialize it
if (!document.hasItem(ITEM_TYPE)) {
_hdb.setListener(document, HDBModelListener.class.getName());
document.setItemValue(ITEM_TYPE, TYPE_STORAGE);
document.setItemValue(ITEM_STORAGE_ID, modelNode.attributeValue("sid"));
document.save();
}
// Initialize eventual children
children = modelNode.elements().iterator();
while (children.hasNext()) {
Element child = (Element) children.next();
initModel(child, document);
}
}
else if (modelNode.getName().equals("singleton-content")) {
HDBModelParams params = new HDBModelParams(TYPE_CONTENT);
document = _hdb.getOrCreateUIDContent(parent, modelNode.attributeValue("sid"), params);
// If the document does not yet have a type item we regard it as just created an initialize it
if (!document.hasItem(ITEM_TYPE)) {
_hdb.setListener(document, HDBModelListener.class.getName());
document.setItemValue(ITEM_TYPE, TYPE_CONTENT);
document.save();
}
Map<String, Object> itemDefaultValues = fetchItemDefaultValues(modelNode, parent);
initContentItems(document, itemDefaultValues);
// Initialize eventual children
children = modelNode.elements().iterator();
while (children.hasNext()) {
Element child = (Element) children.next();
initModel(child, document);
}
}
// We only initialize beyond contents if the model version changed
else if (modelNode.getName().equals("content")) {
if (parent != null && _modelVersionChanged) {
String contentClass = modelNode.attributeValue("contentclass", "");
Map<String, Object> itemDefaultValues = fetchItemDefaultValues(modelNode, parent);
for (WGContent con : parent.getChildContents()) {
if (contentClass.equals(contentClass)) {
initContentItems(con, itemDefaultValues);
// Initialize children
children = modelNode.elements().iterator();
while (children.hasNext()) {
Element child = (Element) children.next();
initModel(child, con);
}
}
}
}
}
}
private void initContentItems(WGContent con, Map<String, Object> itemDefaultValues) throws WGAPIException {
// Initialize items
for (Map.Entry<String,Object> defValue : itemDefaultValues.entrySet()) {
if (!con.hasItem(defValue.getKey())) {
_core.getLog().info("Initializing item '" + defValue.getKey() + "' on document " + con.getTitle());
con.setItemValue(defValue.getKey(), defValue.getValue());
con.saveWithGivenTimestamps(con.getCreated(), con.getLastModified());
}
}
}
private Map<String, Object> fetchItemDefaultValues(Element modelNode, WGContent parent) throws WGAPIException {
// Find initial values for items
Map<String,Object> itemDefaultValues = new HashMap<String, Object>();
for (Element item : (List<Element>) modelNode.elements("item")) {
String itemName = item.attributeValue("name");
String defaultValueExpr = item.attributeValue("default");
TMLContext context = new TMLContext(parent, _core, null, null);
ExpressionResult result = ExpressionEngineFactory.getTMLScriptEngine().evaluateExpression(defaultValueExpr, context, ExpressionEngine.TYPE_EXPRESSION, null);
if (!result.isError()) {
itemDefaultValues.put(itemName, result.getResult());
}
else {
_core.getLog().error("Exception determining default value for item '" + itemName + "' in content class '" + modelNode.attributeValue("contentclass", "(unknown)") + "' in HDB model", result.getException());
}
}
return itemDefaultValues;
}
private void readDefinition(WGFileContainer model) throws DocumentException, WGAPIException, NoSuchAlgorithmException, IOException {
SAXReader saxReader = new SAXReader();
MD5HashingInputStream inputStream = new MD5HashingInputStream(model.getFileData(MODEL_FILE));
_definition = saxReader.read(new InputStreamReader(inputStream, "UTF-8"));
inputStream.close();
String redirection = _definition.getRootElement().attributeValue("redirect");
if (redirection != null) {
WGFileContainer redirectModel = model.getDatabase().getFileContainer(redirection);
readDefinition(redirectModel);
return;
}
_definitionTime = model.getLastModified().getTime();
String versionStr = _definition.getRootElement().attributeValue("version", "1.0");
try {
_definitionHash = inputStream.getHash();
}
catch (NumberFormatException e) {
LOG.error("Exception parsing model version '" + versionStr + "'. Fallback to version 1.0.", e);
}
}
public Element getModelForContent(WGContent content) throws WGAPIException {
Iterator contentPath = getContentPath(content).iterator();
Element currentModelNode = _definition.getRootElement();
while (contentPath.hasNext()) {
WGContent partContent = (WGContent) contentPath.next();
Element foundModel = findChildModelForContent(currentModelNode, partContent);
if (foundModel != null) {
currentModelNode = foundModel;
}
else {
return null;
}
}
return currentModelNode;
}
private Element findChildModelForContent(Element parentModel, WGContent content) throws WGAPIException {
Iterator modelCandidates = parentModel.elements().iterator();
Element foundModel = null;
while (modelCandidates.hasNext()) {
Element modelCandidate = (Element) modelCandidates.next();
if (isModelMatchingContent(content, modelCandidate)) {
foundModel = modelCandidate;
break;
}
}
return foundModel;
}
private boolean isModelMatchingContent(WGContent content, Element model) throws WGAPIException {
boolean modelMatchesContent = false;
String partContentClass = content.getContentClass();
String partId = getUID(content);
if (model.getName().equals(ELEMENT_STORAGE) && partId != null) {
if (partId.equals(model.attributeValue("sid"))) {
modelMatchesContent = true;
}
}
else if (model.getName().equals(ELEMENT_CONTENT) && partContentClass != null) {
if (partContentClass.equals(model.attributeValue("class"))) {
modelMatchesContent = true;
}
}
return modelMatchesContent;
}
private String getUID(WGContent content) throws WGAPIException {
String partUname = content.getUniqueName();
String partId = null;
if (partUname != null) {
List unameParts = WGUtils.deserializeCollection(partUname, WGHierarchicalDatabase.STORAGE_DELIMITER);
partId = (String) unameParts.get(unameParts.size() - 1);
}
return partId;
}
private List getContentPath(WGContent content) throws WGAPIException {
List contents = new ArrayList();
while (content != null) {
contents.add(content);
content = content.getParentContent();
}
Collections.reverse(contents);
return contents;
}
private WGContent getParentForContentClass(String contentClass, WGContent potentialParent, boolean forceRelative) throws WGAPIException {
Element refModel = null;
if (potentialParent != null && !potentialParent.isDummy()) {
refModel = getModelForContent(potentialParent);
}
List modelsList = getModelsForContentClass(contentClass);
// First try: Look if we find a special position below our potential parent for
// this content class
if (refModel != null) {
Iterator models = modelsList.iterator();
while (models.hasNext()) {
Element contentClassModel = (Element) models.next();
if (contentClassModel.getPath().startsWith(refModel.getPath())) {
WGContent parent = findContentForModel(potentialParent, contentClassModel.getParent(), true);
if (parent != null) {
return parent;
}
}
}
}
// Second try: Find a general position in the hierarchy
if (!forceRelative) {
Iterator models = modelsList.iterator();
while (models.hasNext()) {
Element contentClassModel = (Element) models.next();
WGContent parent = findContentForModel(null, contentClassModel.getParent(), false);
if (parent != null) {
return parent;
}
}
}
return null;
}
private List getModelsForContentClass(String contentClass) {
return _definition.selectNodes("//content[@class='" + contentClass + "']");
}
private WGContent findContentForModel(WGContent ref, Element model, boolean allowContentModels) throws WGAPIException {
Element refModel = null;
if (ref != null) {
refModel = getModelForContent(ref);
}
// Ref document is already correct model?
if (refModel != null && refModel.equals(model)) {
return ref;
}
// Retrieve partial model path between refModel and model (or from model to root if no ref given)
List modelPath = new ArrayList();
Element currentModel = model;
do {
modelPath.add(currentModel);
currentModel = currentModel.getParent();
} while (currentModel != null && !currentModel.getName().equals("hdb-model") && !currentModel.equals(refModel));
// model is no descendant of refModel - This path is wrong
if (ref != null && currentModel == null) {
return null;
}
Collections.reverse(modelPath);
// Traverse the model path and find matching contents
Iterator pathIt = modelPath.iterator();
while (pathIt.hasNext()) {
Element pathModel = (Element) pathIt.next();
if (!allowContentModels && pathModel.getName().equals(ELEMENT_CONTENT)) {
continue;
}
ref = findChildContentForModel(ref, pathModel);
if (ref == null) {
return null;
}
}
return ref;
}
private WGContent findChildContentForModel(WGContent ref, Element pathModel) throws WGAPIException {
Iterator children;
if (ref != null) {
children = ref.getChildContents().iterator();
}
else {
children = _hdb.getRootDocuments().iterator();
}
while (children.hasNext()) {
WGContent child = (WGContent) children.next();
if (isModelMatchingContent(child, pathModel)) {
return child;
}
}
return null;
}
public void close() {
_db.removeDesignChangeListener(this);
}
public void designChanged(WGDesignChangeEvent event) {
try {
// Look if the system file container is in update logs
if (!Groq.selectFrom(event.getUpdateLogs()).wherePropertyEquals("documentKey", SYSTEMFC_DOCKEY).hasNext()) {
return;
}
// If so, we reread the definition in a master session task
MasterSessionTask task = new MasterSessionTask(event.getDatabase()) {
protected void exec(WGDatabase db) throws Throwable {
WGFileContainer system = db.getFileContainer("system");
if (system != null && system.getLastModified().getTime() > _definitionTime && system.hasFile(MODEL_FILE)) {
_core.getLog().info("Updating HDB model for database " + db.getDbReference());
readDefinition(system);
}
}
};
task.runWithExceptions();
}
catch (Throwable e) {
_core.getLog().error("Error updating HDB model for database" + event.getDatabase().getDbReference(), e);
}
}
public boolean isTemporary() {
return false;
}
public boolean isStorage(WGContent content) throws WGAPIException {
return "storage".equals(content.getItemValue("$hdbmodel_type")) || _hdb.isStorage(content);
}
public static void createModelObject(WGACore core, WGDatabase db) throws WGAPIException, DocumentException, NoSuchAlgorithmException, IOException {
WGFileContainer system = db.getFileContainer("system");
if (system == null) {
return;
}
if (!system.hasFile(MODEL_FILE)) {
return;
}
core.getLog().info("Initializing HDB model for database " + db.getDbReference());
HDBModel model = new HDBModel(core, db, system);
db.setAttribute(WGACore.DBATTRIB_HDBMODEL, model);
core.getTmlscriptGlobalRegistry().registerDBGlobal(new TMLScriptGlobal(HDBMODEL_GLOBAL, TMLScriptGlobal.TYPE_OBJECT, model), db);
}
public void initSubmodel(WGContent newContent) throws WGAPIException, HDBModelException {
Element model = getModelForContent(newContent);
if (model == null) {
throw new HDBModelException("Cannot find model for " + newContent.getDocumentKey());
}
Iterator childModels = model.elements().iterator();
while (childModels.hasNext()) {
Element childModel = (Element) childModels.next();
initModel(childModel, newContent);
}
}
public WGContent createContent(HDBModelParams params, WGContent ref) throws HDBModelException, WGAPIException {
// Search for the right parent to store this document
WGContent parent = getParentForContentClass(params.getContentClass(), ref, false);
if (parent == null) {
if (ref != null) {
throw new HDBModelException("HDB model cannot find correct parent for content class '" + params.getContentClass() + "' on ref document '" + ref.getDocumentKey() + "' of class " + ref.getContentClass());
}
else {
throw new HDBModelException("HDB model cannot find correct parent for content class '" + params.getContentClass() + "' without ref document");
}
}
// Create the content
params.setCreateContentID(UIDGenerator.generateUID());
WGContent newContent = _hdb.createContent(parent, params.getContentClass() + " " + params.getCreateContentID(), params);
return newContent;
}
public WGContent createContent(String contentClass, WGContent ref) throws WGAPIException, HDBModelException {
HDBModelParams params = new HDBModelParams(HDBModel.TYPE_CONTENT);
params.setContentClass(contentClass);
return createContent(params, ref);
}
public WGContent createContent(String contentClass, WGContent ref, Object param) throws WGAPIException, HDBModelException {
HDBModelParams params = new HDBModelParams(HDBModel.TYPE_CONTENT);
params.setContentClass(contentClass);
params.setCustomParam(param);
return createContent(params, ref);
}
public void updateContent(WGContent content) throws WGAPIException {
HDBModelParams params = new HDBModelParams(content);
_hdb.updateContent(content, params);
}
public void updateContent(WGContent content, HDBModelProcess process) throws WGAPIException {
HDBModelParams params = new HDBModelParams(content);
params.setProcess(process);
_hdb.updateContent(content, params);
}
public void updateContent(WGContent content, String tmlscriptModule) throws WGAPIException {
HDBModelProcess process = new TMLScriptHDBModelProcess(getCore(), getHdb(), tmlscriptModule);
updateContent(content, process);
}
public void deleteContent(WGContent content) throws WGAPIException {
HDBModelParams params = new HDBModelParams(content);
_hdb.deleteContent(content, params);
}
public void moveContent(WGContent content, WGContent ref) throws WGAPIException, HDBModelException {
HDBModelParams params = new HDBModelParams(content);
WGContent newParent = getParentForContentClass(params.getContentClass(), ref, true);
if (newParent == null) {
throw new HDBModelException("Cannot find valid position for content class '" + params.getContentClass() + "' below move target " + ref.getDocumentKey());
}
_hdb.moveContent(content, newParent);
}
public WGHierarchicalDatabase getHdb() {
return _hdb;
}
public WGAbstractResultSet getRelationTargets(WGContent content, String contentClass, String relation) throws WGAPIException, HDBModelException {
Element refNode = getModelForContent(content);
if (refNode == null) {
throw new HDBModelException("Cannot find model for content " + content.getContentKey() + " of class " + content.getContentClass());
}
Element contentNode = null;
if ("content".equals(refNode.getName()) && (contentClass == null || contentClass.equals(refNode.attributeValue("class")))) {
contentNode = refNode;
}
else {
contentNode = findChildModelOfClass(refNode, contentClass);
if (contentNode == null) {
throw new HDBModelException("Cannot find direct child content class " + contentClass + " from ref document '" + content.getContentKey() + "' of class " + content.getContentClass());
}
}
Element relationNode = (Element) contentNode.selectSingleNode("relation[@name='" + relation + "']");
if (relationNode == null) {
throw new HDBModelException("Cannot find relation '" + relation + "' for content class " + content.getContentClass());
}
return getRelationTargets(content, contentClass, relationNode);
}
private Element findChildModelOfClass(Element refNode, String contentClass) {
for (Element child : (List<Element>) refNode.elements()) {
if ("storage".equals(child.getName())) {
Element foundModel = findChildModelOfClass(child, contentClass);
if (foundModel != null) {
return foundModel;
}
}
else if ("content".equals(child.getName())) {
if (contentClass.equals(child.attributeValue("class"))) {
return child;
}
}
}
return null;
}
private WGAbstractResultSet getRelationTargets(WGContent content, String contentClass, Element relationNode) throws WGAPIException, HDBModelException {
WGContent baseContent = null;
// Get target and base class
String targetClass = relationNode.attributeValue("targetclass");
if (targetClass == null) {
throw new HDBModelException("Missing attribute targetclass on relation '" + relationNode.attributeValue("name") + "' of content class '" + content.getContentClass() + "'");
}
String baseClass = relationNode.attributeValue("baseclass");
if (baseClass != null) {
if (baseClass.equals(content.getContentClass())) {
baseContent = content;
}
else {
baseContent = content.getRelation("parent-" + baseClass);
if (baseContent == null) {
throw new HDBModelException("Cannot find base class '" + baseClass + "' from content " + content.getContentKey());
}
}
}
List<String> conditions = new ArrayList<String>();
List<String> orders = new ArrayList<String>();
Map<String,Object> params = new HashMap<String,Object>();
params.putAll(Query.buildDefaultQueryParams(content));
// Add relation targets as parameters
for (String relationName : content.getRelationNames()) {
WGContent relationTarget = content.getRelation(relationName);
if (relationTarget != null) {
params.put("relation_" + Query.makeQueryParameterName(relationName), relationTarget);
}
}
// The reference content is itself a parent?
String currentTargetsInclusion = null;
if (!contentClass.equals(content.getContentClass())) {
params.put("relation_parent_" + Query.makeQueryParameterName(content.getContentClass()), content);
}
// If the reference content itself is the content to store the relation on we automatically add all existing relation targets
else {
params.put("target_content", content);
params.put("relation_name", relationNode.attributeValue("name"));
if (relationNode.attributeValue("group", "false").equals("true")) {
currentTargetsInclusion = "content in (select rel.target from ContentRelation rel where rel.group=:relation_name AND rel.parentcontent=:target_content)";
}
else {
currentTargetsInclusion = "content in (select rel.target from ContentRelation rel where rel.name=:relation_name AND rel.parentcontent=:target_content)";
}
}
int paramIdx = 0;
conditions.add("content.contentclass = '" + targetClass + "'");
if (baseContent != null) {
paramIdx++;
params.put("p" + String.valueOf(paramIdx), baseContent);
conditions.add("content.relations['parent-" + baseClass + "'].target = :p" + String.valueOf(paramIdx));
}
// Add filter from target class
String filter = relationNode.attributeValue("filter");
if (filter != null) {
Element baseModel = getModelForContent(baseContent);
Element filterNode = getFilterNode(baseModel, targetClass, filter);
if (filterNode == null) {
throw new HDBModelException("Cannot find filter n '" + filter + "' for content class '" + targetClass + "'");
}
for (Element condition : (List<Element>) filterNode.elements()) {
if (condition.getName().equals("where")) {
conditions.add("(" + condition.getTextTrim() + ")");
}
else if (condition.getName().equals("order")) {
orders.add(condition.getTextTrim());
}
}
}
// Add additional filter from relation
boolean orderCleared = false;
for (Element condition : (List<Element>) relationNode.elements()) {
if (condition.getName().equals("where")) {
conditions.add("(" + condition.getTextTrim() + ")");
}
else if (condition.getName().equals("order")) {
// order tags on relation overwrite the order set from target class filter
if (!orderCleared) {
orders.clear();
orderCleared = true;
}
orders.add(condition.getTextTrim());
}
else if (condition.getName().equals("param")) {
String paramName = condition.attributeValue("name");
String paramExpression = condition.getTextTrim();
TMLContext context = new TMLContext(content, _core, null, null);
ExpressionResult result = ExpressionEngineFactory.getTMLScriptEngine().evaluateExpression(paramExpression, context, ExpressionEngine.TYPE_EXPRESSION, null);
if (!result.isError()) {
params.put(paramName, result.getResult());
}
else {
throw new HDBModelException("Error evaluating filter param " + paramName, result.getException());
}
}
}
String hql = WGUtils.serializeCollection(conditions, " AND ");
if (currentTargetsInclusion != null) {
hql = currentTargetsInclusion + " OR (" + hql + ")";
}
if (orders.size() > 0) {
hql += " ORDER BY " + WGUtils.serializeCollection(orders, ", ");
}
//_core.getLog().info(contentClass + "." + relationNode.attributeValue("name") + ": " + hql);
Map<String,Object> queryParams = new HashMap<String, Object>();
queryParams.put(WGDatabase.QUERYOPTION_QUERY_PARAMETERS, params);
queryParams.put(WGDatabase.QUERYOPTION_CACHERESULT, Boolean.TRUE);
return _db.query("hql", hql, queryParams);
}
private Element getFilterNode(Element baseModel, String targetClass, String filter) {
return (Element) baseModel.selectSingleNode("//content[@class='" + targetClass+ "']/filter[@name='" + filter + "']");
}
public WGAbstractResultSet getRelationSources(String contentClass, String relation, WGContent target) throws WGAPIException {
String hql = "content.contentclass = :contentclass and content.relations[:relname].target = :target";
Map queryParams = new HashMap();
queryParams.put("contentclass", contentClass);
queryParams.put("relname", relation);
queryParams.put("target", target);
Map parameters = new HashMap();
parameters.put(WGDatabase.QUERYOPTION_QUERY_PARAMETERS, queryParams);
parameters.put(WGDatabase.QUERYOPTION_CACHERESULT, Boolean.TRUE);
return _db.query("hql", hql, parameters);
}
public void assignContentUID(WGContent content, String uid) throws WGAPIException {
_hdb.assignContentUID(content, UniqueNamePartFormatter.INSTANCE.format(uid));
}
}