]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.jcr/src/org/argeo/app/jcr/XPathUtils.java
Adapt to changes in Argeo Build and Argeo Commons
[gpl/argeo-suite.git] / org.argeo.app.jcr / src / org / argeo / app / jcr / XPathUtils.java
1 package org.argeo.app.jcr;
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 * @throws RepositoryException
82 */
83 public static String getPropertyDateComparaison(String propertyName, Calendar cal, String lowerOrGreater)
84 throws RepositoryException {
85 if (cal != null) {
86 String jcrDateStr = jcrRefFormatter.format(cal.getTime());
87
88 // jcrDateStr = "2015-08-03T05:00:03:000Z";
89 String result = "@" + propertyName + " " + lowerOrGreater + " xs:dateTime('" + jcrDateStr + "')";
90 return result;
91 }
92 return "";
93 }
94
95 public static String getPropertyEquals(String propertyName, String value) {
96 if (notEmpty(value))
97 return "@" + propertyName + "='" + encodeXPathStringValue(value) + "'";
98 return "";
99 }
100
101 public static String encodeXPathStringValue(String propertyValue) {
102 // TODO implement safer mechanism to escape invalid characters
103 // Also check why we have used this regex in ResourceSerrviceImpl l 474
104 // String cleanedKey = key.replaceAll("(?:')", "''");
105 String result = propertyValue.replaceAll("'", "''");
106 return result;
107 }
108
109 public static void andAppend(StringBuilder builder, String condition) {
110 if (notEmpty(condition)) {
111 builder.append(condition);
112 builder.append(" and ");
113 }
114 }
115
116 public static void appendOrderByProperties(StringBuilder builder, boolean ascending, String... propertyNames) {
117 if (propertyNames.length > 0) {
118 builder.append(" order by ");
119 for (String propName : propertyNames)
120 builder.append("@").append(propName).append(", ");
121 builder = builder.delete(builder.length() - 2, builder.length());
122 if (ascending)
123 builder.append(" ascending ");
124 else
125 builder.append(" descending ");
126 }
127 }
128
129 public static void appendAndPropStringCondition(StringBuilder builder, String propertyName, String filter)
130 throws RepositoryException {
131 if (notEmpty(filter)) {
132 andAppend(builder, getPropertyContains(propertyName, filter));
133 }
134 }
135
136 public static void appendAndNotPropStringCondition(StringBuilder builder, String propertyName, String filter)
137 throws RepositoryException {
138 if (notEmpty(filter)) {
139 String cond = getPropertyContains(propertyName, filter);
140 builder.append(xPathNot(cond));
141 builder.append(" and ");
142 }
143 }
144
145 public static Query createQuery(Session session, String queryString) throws RepositoryException {
146 QueryManager queryManager = session.getWorkspace().getQueryManager();
147 // Localise JCR properties for XPATH
148 queryString = localiseJcrItemNames(queryString);
149 return queryManager.createQuery(queryString, QUERY_XPATH);
150 }
151
152 private final static String NS_JCR = "\\{http://www.jcp.org/jcr/1.0\\}";
153 private final static String NS_NT = "\\{http://www.jcp.org/jcr/nt/1.0\\}";
154 private final static String NS_MIX = "\\{http://www.jcp.org/jcr/mix/1.0\\}";
155
156 /**
157 * Replace the generic namespace with the local "jcr:", "nt:", "mix:" values. It
158 * is a workaround that must be later cleaned
159 */
160 public static String localiseJcrItemNames(String name) {
161 name = name.replaceAll(NS_JCR, "jcr:");
162 name = name.replaceAll(NS_NT, "nt:");
163 name = name.replaceAll(NS_MIX, "mix:");
164 return name;
165 }
166
167 private static boolean notEmpty(String stringToTest) {
168 return !(stringToTest == null || "".equals(stringToTest.trim()));
169 }
170
171 /** Singleton. */
172 private XPathUtils() {
173
174 }
175 }