1 package org
.argeo
.cms
.jcr
.acr
;
3 import static javax
.jcr
.query
.qom
.QueryObjectModelConstants
.JCR_OPERATOR_EQUAL_TO
;
5 import java
.util
.ArrayList
;
8 import javax
.jcr
.Property
;
9 import javax
.jcr
.RepositoryException
;
10 import javax
.jcr
.Session
;
11 import javax
.jcr
.query
.QueryManager
;
12 import javax
.jcr
.query
.qom
.DynamicOperand
;
13 import javax
.jcr
.query
.qom
.QueryObjectModel
;
14 import javax
.jcr
.query
.qom
.QueryObjectModelConstants
;
15 import javax
.jcr
.query
.qom
.QueryObjectModelFactory
;
16 import javax
.jcr
.query
.qom
.Selector
;
17 import javax
.jcr
.query
.qom
.StaticOperand
;
18 import javax
.xml
.namespace
.QName
;
20 import org
.apache
.jackrabbit
.commons
.query
.sql2
.QOMFormatter
;
21 import org
.argeo
.api
.acr
.DName
;
22 import org
.argeo
.api
.acr
.NamespaceUtils
;
23 import org
.argeo
.api
.acr
.search
.BasicSearch
;
24 import org
.argeo
.api
.acr
.search
.Constraint
;
25 import org
.argeo
.api
.acr
.search
.ContentFilter
;
26 import org
.argeo
.api
.acr
.search
.Eq
;
27 import org
.argeo
.api
.acr
.search
.Gt
;
28 import org
.argeo
.api
.acr
.search
.Gte
;
29 import org
.argeo
.api
.acr
.search
.IsContentClass
;
30 import org
.argeo
.api
.acr
.search
.IsDefined
;
31 import org
.argeo
.api
.acr
.search
.Like
;
32 import org
.argeo
.api
.acr
.search
.Lt
;
33 import org
.argeo
.api
.acr
.search
.Lte
;
34 import org
.argeo
.api
.acr
.search
.Not
;
35 import org
.argeo
.api
.acr
.search
.PropertyValueContraint
;
36 import org
.argeo
.api
.cms
.CmsLog
;
38 /** Convert an ACR basic search to a JCR query. */
39 class BasicSearchToQom
{
40 private final static CmsLog log
= CmsLog
.getLog(BasicSearchToQom
.class);
42 private Session session
;
43 private QueryManager queryManager
;
44 private BasicSearch basicSearch
;
45 private QueryObjectModelFactory factory
;
47 private String relPath
;
49 private QName contentClass
= null;
51 private String selectorName
= "content";
53 public BasicSearchToQom(Session session
, BasicSearch basicSearch
, String relPath
) throws RepositoryException
{
54 this.session
= session
;
55 this.queryManager
= session
.getWorkspace().getQueryManager();
56 this.basicSearch
= basicSearch
;
57 this.relPath
= relPath
;
58 factory
= queryManager
.getQOMFactory();
61 public QueryObjectModel
createQuery() throws RepositoryException
{
62 ContentFilter
<?
> where
= basicSearch
.getWhere();
63 // scan for content classes
64 // TODO deal with complex cases of multiple types
66 javax
.jcr
.query
.qom
.Constraint qomConstraint
= toQomConstraint(where
);
67 if (contentClass
== null)
68 throw new IllegalArgumentException("No content class specified");
70 if (relPath
!= null) {
71 qomConstraint
= factory
.and(qomConstraint
, factory
.descendantNode(selectorName
, "/" + relPath
));
74 Selector source
= factory
.selector(NamespaceUtils
.toPrefixedName(contentClass
), selectorName
);
76 QueryObjectModel qom
= factory
.createQuery(source
, qomConstraint
, null, null);
77 if (log
.isTraceEnabled()) {
78 String sql2
= QOMFormatter
.format(qom
);
79 log
.trace("JCR query:\n" + sql2
+ "\n");
84 private javax
.jcr
.query
.qom
.Constraint
toQomConstraint(Constraint constraint
) throws RepositoryException
{
85 // javax.jcr.query.qom.Constraint qomConstraint;
86 if (constraint
instanceof ContentFilter
<?
> where
) {
87 List
<Constraint
> constraints
= new ArrayList
<>();
88 for (Constraint c
: where
.getConstraints()) {
89 if (c
instanceof IsContentClass icc
) {
90 if (icc
.getContentClasses().length
> 1 || contentClass
!= null)
91 throw new IllegalArgumentException("Multiple content class is not supported");
92 contentClass
= icc
.getContentClasses()[0];
98 if (constraints
.isEmpty()) {
100 } else if (constraints
.size() == 1) {
101 return toQomConstraint(constraints
.get(0));
103 javax
.jcr
.query
.qom
.Constraint currQomConstraint
= toQomConstraint(constraints
.get(0));
104 // QOM constraint may be null because only content classes where specified
105 while (currQomConstraint
== null) {
106 constraints
.remove(0);
107 if (constraints
.isEmpty())
109 currQomConstraint
= toQomConstraint(constraints
.get(0));
111 assert currQomConstraint
!= null : "currQomConstraint is null : " + constraints
.get(0);
112 for (int i
= 1; i
< constraints
.size(); i
++) {
113 Constraint c
= constraints
.get(i
);
114 javax
.jcr
.query
.qom
.Constraint subQomConstraint
= toQomConstraint(c
);
115 if (subQomConstraint
!= null) { // isContentClass leads to null QOM constraint
116 assert subQomConstraint
!= null : "subQomConstraint";
117 if (where
.isUnion()) {
118 currQomConstraint
= factory
.or(currQomConstraint
, subQomConstraint
);
120 currQomConstraint
= factory
.and(currQomConstraint
, subQomConstraint
);
124 return currQomConstraint
;
127 } else if (constraint
instanceof PropertyValueContraint comp
) {
128 QName prop
= comp
.getProp();
129 if (DName
.creationdate
.equals(prop
))
130 prop
= JcrName
.created
.qName();
131 else if (DName
.getlastmodified
.equals(prop
))
132 prop
= JcrName
.lastModified
.qName();
134 DynamicOperand dynamicOperand
= factory
.propertyValue(selectorName
, NamespaceUtils
.toPrefixedName(prop
));
135 // TODO better convert attribute value
136 StaticOperand staticOperand
= factory
137 .literal(JcrContent
.convertSingleObject(session
.getValueFactory(), comp
.getValue()));
138 javax
.jcr
.query
.qom
.Constraint res
;
139 if (comp
instanceof Eq
)
140 res
= factory
.comparison(dynamicOperand
, QueryObjectModelConstants
.JCR_OPERATOR_EQUAL_TO
,
142 else if (comp
instanceof Lt
)
143 res
= factory
.comparison(dynamicOperand
, QueryObjectModelConstants
.JCR_OPERATOR_LESS_THAN
,
145 else if (comp
instanceof Lte
)
146 res
= factory
.comparison(dynamicOperand
, QueryObjectModelConstants
.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO
,
148 else if (comp
instanceof Gt
)
149 res
= factory
.comparison(dynamicOperand
, QueryObjectModelConstants
.JCR_OPERATOR_GREATER_THAN
,
151 else if (comp
instanceof Gte
)
152 res
= factory
.comparison(dynamicOperand
,
153 QueryObjectModelConstants
.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO
, staticOperand
);
154 else if (comp
instanceof Like
)
155 res
= factory
.comparison(dynamicOperand
, QueryObjectModelConstants
.JCR_OPERATOR_LIKE
, staticOperand
);
157 throw new UnsupportedOperationException("Constraint of type " + comp
.getClass() + " is not supported");
159 } else if (constraint
instanceof Not not
) {
160 return factory
.not(toQomConstraint(not
.getNegated()));
161 } else if (constraint
instanceof IsDefined comp
) {
162 QName prop
= comp
.getProp();
163 if (DName
.checkedIn
.equals(prop
) || DName
.checkedOut
.equals(prop
)) {
164 DynamicOperand dynamicOperand
= factory
.propertyValue(selectorName
, Property
.JCR_IS_CHECKED_OUT
);
165 StaticOperand staticOperand
= factory
166 .literal(session
.getValueFactory().createValue(DName
.checkedOut
.equals(prop
)));
167 return factory
.comparison(dynamicOperand
, JCR_OPERATOR_EQUAL_TO
, staticOperand
);
169 return factory
.propertyExistence(selectorName
, NamespaceUtils
.toPrefixedName(prop
));
172 throw new IllegalArgumentException("Constraint " + constraint
.getClass() + " is not supported");
174 // return qomConstraint;