]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.core/src/org/argeo/app/core/XPathUtils.java
Instrument image utils
[gpl/argeo-suite.git] / org.argeo.app.core / src / org / argeo / app / core / XPathUtils.java
1 package org.argeo.app.core;
2
3 import java.text.DateFormat;
4 import java.text.SimpleDateFormat;
5 import java.util.Calendar;
6
7 import javax.jcr.RepositoryException;
8 import javax.jcr.Session;
9 import javax.jcr.query.Query;
10 import javax.jcr.query.QueryManager;
11
12 import org.apache.jackrabbit.util.ISO9075;
13 import org.argeo.api.cms.CmsLog;
14
15 /** Ease XPath generation for JCR requests */
16 public class XPathUtils {
17 private final static CmsLog log = CmsLog.getLog(XPathUtils.class);
18
19 private final static String QUERY_XPATH = "xpath";
20
21 public static String descendantFrom(String parentPath) {
22 if (notEmpty(parentPath)) {
23 if ("/".equals(parentPath))
24 parentPath = "";
25 // Hardcoded dependency to Jackrabbit. Remove
26 String result = "/jcr:root" + ISO9075.encodePath(parentPath);
27 if (log.isTraceEnabled()) {
28 String result2 = "/jcr:root" + parentPath;
29 if (!result2.equals(result))
30 log.warn("Encoded Path " + result2 + " --> " + result);
31 }
32 return result;
33 } else
34 return "";
35 }
36
37 public static String localAnd(String... conditions) {
38 StringBuilder builder = new StringBuilder();
39 for (String condition : conditions) {
40 if (notEmpty(condition)) {
41 builder.append(" ").append(condition).append(" and ");
42 }
43 }
44 if (builder.length() > 3)
45 return builder.substring(0, builder.length() - 4);
46 else
47 return "";
48 }
49
50 public static String xPathNot(String condition) {
51 if (notEmpty(condition))
52 return "not(" + condition + ")";
53 else
54 return "";
55 }
56
57 public static String getFreeTextConstraint(String filter) throws RepositoryException {
58 StringBuilder builder = new StringBuilder();
59 if (notEmpty(filter)) {
60 String[] strs = filter.trim().split(" ");
61 for (String token : strs) {
62 builder.append("jcr:contains(.,'*" + encodeXPathStringValue(token) + "*') and ");
63 }
64 return builder.substring(0, builder.length() - 4);
65 }
66 return "";
67 }
68
69 public static String getPropertyContains(String propertyName, String filter) throws RepositoryException {
70 if (notEmpty(filter))
71 return "jcr:contains(@" + propertyName + ",'*" + encodeXPathStringValue(filter) + "*')";
72 return "";
73 }
74
75 private final static DateFormat jcrRefFormatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'+02:00'");
76
77 /**
78 * @param propertyName
79 * @param calendar the reference date
80 * @param lowerOrGreater "<", ">" TODO validate ">="
81 * @return
82 * @throws RepositoryException
83 */
84 public static String getPropertyDateComparaison(String propertyName, Calendar cal, String lowerOrGreater)
85 throws RepositoryException {
86 if (cal != null) {
87 String jcrDateStr = jcrRefFormatter.format(cal.getTime());
88
89 // jcrDateStr = "2015-08-03T05:00:03:000Z";
90 String result = "@" + propertyName + " " + lowerOrGreater + " xs:dateTime('" + jcrDateStr + "')";
91 return result;
92 }
93 return "";
94 }
95
96 public static String getPropertyEquals(String propertyName, String value) {
97 if (notEmpty(value))
98 return "@" + propertyName + "='" + encodeXPathStringValue(value) + "'";
99 return "";
100 }
101
102 public static String encodeXPathStringValue(String propertyValue) {
103 // TODO implement safer mechanism to escape invalid characters
104 // Also check why we have used this regex in ResourceSerrviceImpl l 474
105 // String cleanedKey = key.replaceAll("(?:')", "''");
106 String result = propertyValue.replaceAll("'", "''");
107 return result;
108 }
109
110 public static void andAppend(StringBuilder builder, String condition) {
111 if (notEmpty(condition)) {
112 builder.append(condition);
113 builder.append(" and ");
114 }
115 }
116
117 public static void appendOrderByProperties(StringBuilder builder, boolean ascending, String... propertyNames) {
118 if (propertyNames.length > 0) {
119 builder.append(" order by ");
120 for (String propName : propertyNames)
121 builder.append("@").append(propName).append(", ");
122 builder = builder.delete(builder.length() - 2, builder.length());
123 if (ascending)
124 builder.append(" ascending ");
125 else
126 builder.append(" descending ");
127 }
128 }
129
130 public static void appendAndPropStringCondition(StringBuilder builder, String propertyName, String filter)
131 throws RepositoryException {
132 if (notEmpty(filter)) {
133 andAppend(builder, getPropertyContains(propertyName, filter));
134 }
135 }
136
137 public static void appendAndNotPropStringCondition(StringBuilder builder, String propertyName, String filter)
138 throws RepositoryException {
139 if (notEmpty(filter)) {
140 String cond = getPropertyContains(propertyName, filter);
141 builder.append(xPathNot(cond));
142 builder.append(" and ");
143 }
144 }
145
146 public static Query createQuery(Session session, String queryString) throws RepositoryException {
147 QueryManager queryManager = session.getWorkspace().getQueryManager();
148 // Localise JCR properties for XPATH
149 queryString = localiseJcrItemNames(queryString);
150 return queryManager.createQuery(queryString, QUERY_XPATH);
151 }
152
153 private final static String NS_JCR = "\\{http://www.jcp.org/jcr/1.0\\}";
154 private final static String NS_NT = "\\{http://www.jcp.org/jcr/nt/1.0\\}";
155 private final static String NS_MIX = "\\{http://www.jcp.org/jcr/mix/1.0\\}";
156
157 /**
158 * Replace the generic namespace with the local "jcr:", "nt:", "mix:" values. It
159 * is a workaround that must be later cleaned
160 */
161 public static String localiseJcrItemNames(String name) {
162 name = name.replaceAll(NS_JCR, "jcr:");
163 name = name.replaceAll(NS_NT, "nt:");
164 name = name.replaceAll(NS_MIX, "mix:");
165 return name;
166 }
167
168 private static boolean notEmpty(String stringToTest) {
169 return !(stringToTest == null || "".equals(stringToTest.trim()));
170 }
171
172 /** Singleton. */
173 private XPathUtils() {
174
175 }
176 }