]> git.argeo.org Git - gpl/argeo-jcr.git/blob - org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/BasicSearchToQom.java
72940705a0f07aa2f1ce0bcb828cfa025375a50d
[gpl/argeo-jcr.git] / org.argeo.cms.jcr / src / org / argeo / cms / jcr / acr / BasicSearchToQom.java
1 package org.argeo.cms.jcr.acr;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.jcr.RepositoryException;
7 import javax.jcr.Session;
8 import javax.jcr.query.QueryManager;
9 import javax.jcr.query.qom.DynamicOperand;
10 import javax.jcr.query.qom.QueryObjectModel;
11 import javax.jcr.query.qom.QueryObjectModelConstants;
12 import javax.jcr.query.qom.QueryObjectModelFactory;
13 import javax.jcr.query.qom.Selector;
14 import javax.jcr.query.qom.StaticOperand;
15 import javax.xml.namespace.QName;
16
17 import org.apache.jackrabbit.commons.query.sql2.QOMFormatter;
18 import org.argeo.api.acr.NamespaceUtils;
19 import org.argeo.api.acr.search.BasicSearch;
20 import org.argeo.api.acr.search.Constraint;
21 import org.argeo.api.acr.search.ContentFilter;
22 import org.argeo.api.acr.search.ContentFilter.Eq;
23 import org.argeo.api.acr.search.ContentFilter.IsContentClass;
24 import org.argeo.api.acr.search.ContentFilter.Not;
25 import org.argeo.api.cms.CmsLog;
26
27 /** Convert an ACR basic search to a JCR query. */
28 class BasicSearchToQom {
29 private final static CmsLog log = CmsLog.getLog(BasicSearchToQom.class);
30
31 private Session session;
32 private QueryManager queryManager;
33 private BasicSearch basicSearch;
34 private QueryObjectModelFactory factory;
35
36 private String relPath;
37
38 private QName contentClass = null;
39
40 private String selectorName = "content";
41
42 public BasicSearchToQom(Session session, BasicSearch basicSearch, String relPath) throws RepositoryException {
43 this.session = session;
44 this.queryManager = session.getWorkspace().getQueryManager();
45 this.basicSearch = basicSearch;
46 this.relPath = relPath;
47 factory = queryManager.getQOMFactory();
48 }
49
50 public QueryObjectModel createQuery() throws RepositoryException {
51 ContentFilter<?> where = basicSearch.getWhere();
52 // scan for content classes
53 // TODO deal with complex cases of multiple types
54
55 javax.jcr.query.qom.Constraint qomConstraint = toQomConstraint(where);
56 if (contentClass == null)
57 throw new IllegalArgumentException("No content class specified");
58
59 if (relPath != null) {
60 qomConstraint = factory.and(qomConstraint, factory.descendantNode(selectorName, "/" + relPath));
61 }
62
63 Selector source = factory.selector(NamespaceUtils.toPrefixedName(contentClass), selectorName);
64
65 QueryObjectModel qom = factory.createQuery(source, qomConstraint, null, null);
66 if (log.isDebugEnabled()) {
67 String sql2 = QOMFormatter.format(qom);
68 log.debug("JCR query:\n" + sql2 + "\n");
69 }
70 return qom;
71 }
72
73 private javax.jcr.query.qom.Constraint toQomConstraint(Constraint constraint) throws RepositoryException {
74 // javax.jcr.query.qom.Constraint qomConstraint;
75 if (constraint instanceof ContentFilter<?> where) {
76 List<Constraint> constraints = new ArrayList<>();
77 for (Constraint c : where.getConstraints()) {
78 if (c instanceof IsContentClass icc) {
79 if (icc.getContentClasses().length > 1 || contentClass != null)
80 throw new IllegalArgumentException("Multiple content class is not supported");
81 contentClass = icc.getContentClasses()[0];
82 } else {
83 constraints.add(c);
84 }
85 }
86
87 if (constraints.isEmpty()) {
88 return null;
89 } else if (constraints.size() == 1) {
90 return toQomConstraint(constraints.get(0));
91 } else {
92 javax.jcr.query.qom.Constraint currQomConstraint = toQomConstraint(constraints.get(0));
93 // QOM constraint may be null because only content classes where specified
94 while (currQomConstraint == null) {
95 constraints.remove(0);
96 if (constraints.isEmpty())
97 return null;
98 currQomConstraint = toQomConstraint(constraints.get(0));
99 }
100 assert currQomConstraint != null : "currQomConstraint is null : " + constraints.get(0);
101 for (int i = 1; i < constraints.size(); i++) {
102 Constraint c = constraints.get(i);
103 javax.jcr.query.qom.Constraint subQomConstraint = toQomConstraint(c);
104 if (subQomConstraint != null) { // isContentClass leads to null QOM constraint
105 assert subQomConstraint != null : "subQomConstraint";
106 if (where.isUnion()) {
107 currQomConstraint = factory.or(currQomConstraint, subQomConstraint);
108 } else {
109 currQomConstraint = factory.and(currQomConstraint, subQomConstraint);
110 }
111 }
112 }
113 return currQomConstraint;
114 }
115
116 } else if (constraint instanceof Eq comp) {
117 DynamicOperand dynamicOperand = factory.propertyValue(selectorName,
118 NamespaceUtils.toPrefixedName(comp.getProp()));
119 // TODO better convert attribute value
120 StaticOperand staticOperand = factory
121 .literal(session.getValueFactory().createValue(comp.getValue().toString()));
122 return factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, staticOperand);
123 } else if (constraint instanceof Not not) {
124 return factory.not(toQomConstraint(not.getNegated()));
125 } else {
126 throw new IllegalArgumentException("Constraint " + constraint.getClass() + " is not supported");
127 }
128 // return qomConstraint;
129 }
130 }