X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=org.argeo.app.core%2Fsrc%2Forg%2Fargeo%2Fapp%2Fcore%2FXPathUtils.java;fp=org.argeo.app.core%2Fsrc%2Forg%2Fargeo%2Fapp%2Fcore%2FXPathUtils.java;h=f86445c7072b09fa6a59a8f12db39171d4f61a1f;hp=0000000000000000000000000000000000000000;hb=6e56ffa34cb02ab04d028423aea342e3dfed4358;hpb=c285180bece610b2c2921d44fe14b6dde2123efa diff --git a/org.argeo.app.core/src/org/argeo/app/core/XPathUtils.java b/org.argeo.app.core/src/org/argeo/app/core/XPathUtils.java new file mode 100644 index 0000000..f86445c --- /dev/null +++ b/org.argeo.app.core/src/org/argeo/app/core/XPathUtils.java @@ -0,0 +1,176 @@ +package org.argeo.app.core; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; + +import org.apache.jackrabbit.util.ISO9075; +import org.argeo.api.cms.CmsLog; + +/** Ease XPath generation for JCR requests */ +public class XPathUtils { + private final static CmsLog log = CmsLog.getLog(XPathUtils.class); + + private final static String QUERY_XPATH = "xpath"; + + public static String descendantFrom(String parentPath) { + if (notEmpty(parentPath)) { + if ("/".equals(parentPath)) + parentPath = ""; + // Hardcoded dependency to Jackrabbit. Remove + String result = "/jcr:root" + ISO9075.encodePath(parentPath); + if (log.isTraceEnabled()) { + String result2 = "/jcr:root" + parentPath; + if (!result2.equals(result)) + log.warn("Encoded Path " + result2 + " --> " + result); + } + return result; + } else + return ""; + } + + public static String localAnd(String... conditions) { + StringBuilder builder = new StringBuilder(); + for (String condition : conditions) { + if (notEmpty(condition)) { + builder.append(" ").append(condition).append(" and "); + } + } + if (builder.length() > 3) + return builder.substring(0, builder.length() - 4); + else + return ""; + } + + public static String xPathNot(String condition) { + if (notEmpty(condition)) + return "not(" + condition + ")"; + else + return ""; + } + + public static String getFreeTextConstraint(String filter) throws RepositoryException { + StringBuilder builder = new StringBuilder(); + if (notEmpty(filter)) { + String[] strs = filter.trim().split(" "); + for (String token : strs) { + builder.append("jcr:contains(.,'*" + encodeXPathStringValue(token) + "*') and "); + } + return builder.substring(0, builder.length() - 4); + } + return ""; + } + + public static String getPropertyContains(String propertyName, String filter) throws RepositoryException { + if (notEmpty(filter)) + return "jcr:contains(@" + propertyName + ",'*" + encodeXPathStringValue(filter) + "*')"; + return ""; + } + + private final static DateFormat jcrRefFormatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'+02:00'"); + + /** + * @param propertyName + * @param calendar the reference date + * @param lowerOrGreater "<", ">" TODO validate ">=" + * @return + * @throws RepositoryException + */ + public static String getPropertyDateComparaison(String propertyName, Calendar cal, String lowerOrGreater) + throws RepositoryException { + if (cal != null) { + String jcrDateStr = jcrRefFormatter.format(cal.getTime()); + + // jcrDateStr = "2015-08-03T05:00:03:000Z"; + String result = "@" + propertyName + " " + lowerOrGreater + " xs:dateTime('" + jcrDateStr + "')"; + return result; + } + return ""; + } + + public static String getPropertyEquals(String propertyName, String value) { + if (notEmpty(value)) + return "@" + propertyName + "='" + encodeXPathStringValue(value) + "'"; + return ""; + } + + public static String encodeXPathStringValue(String propertyValue) { + // TODO implement safer mechanism to escape invalid characters + // Also check why we have used this regex in ResourceSerrviceImpl l 474 + // String cleanedKey = key.replaceAll("(?:')", "''"); + String result = propertyValue.replaceAll("'", "''"); + return result; + } + + public static void andAppend(StringBuilder builder, String condition) { + if (notEmpty(condition)) { + builder.append(condition); + builder.append(" and "); + } + } + + public static void appendOrderByProperties(StringBuilder builder, boolean ascending, String... propertyNames) { + if (propertyNames.length > 0) { + builder.append(" order by "); + for (String propName : propertyNames) + builder.append("@").append(propName).append(", "); + builder = builder.delete(builder.length() - 2, builder.length()); + if (ascending) + builder.append(" ascending "); + else + builder.append(" descending "); + } + } + + public static void appendAndPropStringCondition(StringBuilder builder, String propertyName, String filter) + throws RepositoryException { + if (notEmpty(filter)) { + andAppend(builder, getPropertyContains(propertyName, filter)); + } + } + + public static void appendAndNotPropStringCondition(StringBuilder builder, String propertyName, String filter) + throws RepositoryException { + if (notEmpty(filter)) { + String cond = getPropertyContains(propertyName, filter); + builder.append(xPathNot(cond)); + builder.append(" and "); + } + } + + public static Query createQuery(Session session, String queryString) throws RepositoryException { + QueryManager queryManager = session.getWorkspace().getQueryManager(); + // Localise JCR properties for XPATH + queryString = localiseJcrItemNames(queryString); + return queryManager.createQuery(queryString, QUERY_XPATH); + } + + private final static String NS_JCR = "\\{http://www.jcp.org/jcr/1.0\\}"; + private final static String NS_NT = "\\{http://www.jcp.org/jcr/nt/1.0\\}"; + private final static String NS_MIX = "\\{http://www.jcp.org/jcr/mix/1.0\\}"; + + /** + * Replace the generic namespace with the local "jcr:", "nt:", "mix:" values. It + * is a workaround that must be later cleaned + */ + public static String localiseJcrItemNames(String name) { + name = name.replaceAll(NS_JCR, "jcr:"); + name = name.replaceAll(NS_NT, "nt:"); + name = name.replaceAll(NS_MIX, "mix:"); + return name; + } + + private static boolean notEmpty(String stringToTest) { + return !(stringToTest == null || "".equals(stringToTest.trim())); + } + + /** Singleton. */ + private XPathUtils() { + + } +}