1 package org
.argeo
.cms
.jcr
.acr
;
3 import java
.util
.ArrayList
;
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
;
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
;
27 /** Convert an ACR basic search to a JCR query. */
28 class BasicSearchToQom
{
29 private final static CmsLog log
= CmsLog
.getLog(BasicSearchToQom
.class);
31 private Session session
;
32 private QueryManager queryManager
;
33 private BasicSearch basicSearch
;
34 private QueryObjectModelFactory factory
;
36 private String relPath
;
38 private QName contentClass
= null;
40 private String selectorName
= "content";
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();
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
55 javax
.jcr
.query
.qom
.Constraint qomConstraint
= toQomConstraint(where
);
56 if (contentClass
== null)
57 throw new IllegalArgumentException("No content class specified");
59 if (relPath
!= null) {
60 qomConstraint
= factory
.and(qomConstraint
, factory
.descendantNode(selectorName
, "/" + relPath
));
63 Selector source
= factory
.selector(NamespaceUtils
.toPrefixedName(contentClass
), selectorName
);
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");
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];
87 if (constraints
.isEmpty()) {
89 } else if (constraints
.size() == 1) {
90 return toQomConstraint(constraints
.get(0));
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())
98 currQomConstraint
= toQomConstraint(constraints
.get(0));
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
);
109 currQomConstraint
= factory
.and(currQomConstraint
, subQomConstraint
);
113 return currQomConstraint
;
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()));
126 throw new IllegalArgumentException("Constraint " + constraint
.getClass() + " is not supported");
128 // return qomConstraint;