1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.internal.objects.classes

File ImplicitlyAllowedValuesDBListQueryBuilder.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

18
50
4
1
183
111
18
0.36
12.5
4
4.5

Classes

Class Line # Actions
ImplicitlyAllowedValuesDBListQueryBuilder 50 50 0% 18 0
1.0100%
 

Contributing tests

This file is covered by 7 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.internal.objects.classes;
21   
22    import java.util.ArrayList;
23    import java.util.HashMap;
24    import java.util.List;
25    import java.util.Map;
26   
27    import javax.inject.Inject;
28    import javax.inject.Named;
29    import javax.inject.Singleton;
30   
31    import org.xwiki.component.annotation.Component;
32    import org.xwiki.query.Query;
33    import org.xwiki.query.QueryBuilder;
34    import org.xwiki.query.QueryException;
35    import org.xwiki.query.QueryFilter;
36    import org.xwiki.query.QueryManager;
37    import org.xwiki.text.StringUtils;
38   
39    import com.xpn.xwiki.objects.classes.DBListClass;
40   
41    /**
42    * Builds a query from the meta data of a Database List property.
43    *
44    * @version $Id: 7edc2058e5ee229a7ed7b16a750aa2062cc57851 $
45    * @since 9.8RC1
46    */
47    @Component
48    @Named("implicitlyAllowedValues")
49    @Singleton
 
50    public class ImplicitlyAllowedValuesDBListQueryBuilder implements QueryBuilder<DBListClass>
51    {
52    private static final String DOC_PREFIX = "doc.";
53   
54    private static final String OBJ_PREFIX = "obj.";
55   
56    private static final String CLASS_NAME = "className";
57   
58    private static final String TEMPLATE_NAME = "templateName";
59   
60    private static final String COLUMN_SEPARATOR = ", ";
61   
62    @Inject
63    private QueryManager queryManager;
64   
65    @Inject
66    @Named("viewableAllowedDBListPropertyValue")
67    private QueryFilter viewableValueFilter;
68   
69    /**
70    * {@inheritDoc} The query is constructed according to the following rules:
71    * <ul>
72    * <li>If no class name, id or value fields are selected, return a query that returns no rows.</li>
73    * <li>If only the class name is provided, select all document names which have an object of that type.</li>
74    * <li>If only one of id and value is provided, select just one column.</li>
75    * <li>If id = value, select just one column.</li>
76    * <li>If no class name is provided, assume the fields are document properties.</li>
77    * </ul>
78    * If there are two columns selected, use the first one as the stored value and the second one as the displayed
79    * value.
80    *
81    * @see QueryBuilder#build(java.lang.Object)
82    */
 
83  129 toggle @Override
84    public Query build(DBListClass dbListClass) throws QueryException
85    {
86  129 String className = StringUtils.defaultString(dbListClass.getClassname());
87  129 String idField = StringUtils.defaultString(dbListClass.getIdField());
88  129 String valueField = StringUtils.defaultString(dbListClass.getValueField());
89   
90  129 boolean hasClassName = !StringUtils.isBlank(className);
91  129 boolean hasIdField = !StringUtils.isBlank(idField);
92  129 boolean hasValueField = !StringUtils.isBlank(valueField);
93   
94    // Initialize with default query (that returns no rows).
95  129 String statement = "select doc.name from XWikiDocument doc where 1 = 0";
96  129 Map<String, Object> parameters = new HashMap<>();
97   
98  129 if (hasIdField || hasValueField) {
99  106 statement = getStatementWhenIdValueFieldsAreSpecified(className, idField, valueField, hasClassName,
100    hasIdField, hasValueField, parameters);
101  23 } else if (hasClassName) {
102  2 statement = "select distinct doc.fullName from XWikiDocument as doc, BaseObject as obj"
103    + " where doc.fullName = obj.name and obj.className = :className and doc.fullName <> :templateName";
104  2 parameters.put(CLASS_NAME, className);
105  2 parameters.put(TEMPLATE_NAME, getTemplateName(className));
106    }
107   
108  129 Query query = this.queryManager.createQuery(statement, Query.HQL);
109  129 query.setWiki(dbListClass.getOwnerDocument().getDocumentReference().getWikiReference().getName());
110  129 for (Map.Entry<String, Object> entry : parameters.entrySet()) {
111  190 query.bindValue(entry.getKey(), entry.getValue());
112    }
113  129 query.addFilter(this.viewableValueFilter);
114   
115  129 return query;
116    }
117   
 
118  197 toggle private void addFieldToQuery(String fieldName, String fieldAlias, boolean hasClassName, List<String> selectClause,
119    List<String> fromClause, List<String> whereClause, Map<String, Object> parameters)
120    {
121  197 if (fieldName.startsWith(DOC_PREFIX) || fieldName.startsWith(OBJ_PREFIX)) {
122  106 selectClause.add(fieldName);
123  91 } else if (!hasClassName) {
124  9 selectClause.add(DOC_PREFIX + fieldName);
125    } else {
126  82 selectClause.add(fieldAlias + ".value");
127  82 fromClause.add("StringProperty as " + fieldAlias);
128  82 whereClause.add(String.format("obj.id = %1$s.id.id and %1$s.id.name = :%1$s", fieldAlias));
129  82 parameters.put(fieldAlias, fieldName);
130    }
131    }
132   
 
133  115 toggle private String getStatementWhenIdValueFieldsAreSpecified(String className, String idField, String valueField,
134    boolean hasClassName, boolean hasIdField, boolean hasValueField, Map<String, Object> parameters)
135    {
136    // Make sure we always have an id field. Ignore the value field if it duplicates the id field.
137  115 if (!hasIdField || idField.equals(valueField)) {
138  9 return getStatementWhenIdValueFieldsAreSpecified(className, valueField, "", hasClassName, true, false,
139    parameters);
140    }
141   
142  106 List<String> selectClause = new ArrayList<>();
143  106 List<String> fromClause = new ArrayList<>();
144  106 List<String> whereClause = new ArrayList<>();
145   
146    // We need to select the document in order to be able to check access rights on the results. At the same time we
147    // want to skip this column when filtering the Database List property values.
148  106 selectClause.add("doc.fullName as unfilterable0");
149  106 fromClause.add("XWikiDocument as doc");
150   
151    // We need to join the objects table if the class name is specified or if one of the selected columns is an
152    // object property.
153  106 if (hasClassName || idField.startsWith(OBJ_PREFIX) || valueField.startsWith(OBJ_PREFIX)) {
154  60 fromClause.add("BaseObject as obj");
155  60 whereClause.add("doc.fullName = obj.name");
156  60 if (hasClassName) {
157  52 whereClause.add("obj.className = :className and doc.fullName <> :templateName");
158  52 parameters.put(CLASS_NAME, className);
159  52 parameters.put(TEMPLATE_NAME, getTemplateName(className));
160    }
161    }
162   
163  106 addFieldToQuery(idField, "idProp", hasClassName, selectClause, fromClause, whereClause, parameters);
164   
165  106 if (hasValueField) {
166  91 addFieldToQuery(valueField, "valueProp", hasClassName, selectClause, fromClause, whereClause, parameters);
167    }
168   
169  106 StringBuilder statementBuilder =
170    new StringBuilder("select distinct ").append(StringUtils.join(selectClause, COLUMN_SEPARATOR))
171    .append(" from ").append(StringUtils.join(fromClause, COLUMN_SEPARATOR));
172  106 if (whereClause.size() > 0) {
173  60 statementBuilder.append(" where ").append(StringUtils.join(whereClause, " and "));
174    }
175   
176  106 return statementBuilder.toString();
177    }
178   
 
179  54 toggle private String getTemplateName(String className)
180    {
181  54 return StringUtils.removeEnd(className, "Class") + "Template";
182    }
183    }