Unverified Commit 28116e80 authored by Francesco Chicchiricco's avatar Francesco Chicchiricco
Browse files

Bump upgrade to Syncope 2.0.3

parent 3510ce4d
......@@ -6,7 +6,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -143,25 +143,43 @@ limitations under the License.
<phase>process-resources</phase>
<configuration>
<target>
<unzip src="${settings.localRepository}/org/activiti/activiti-webapp-explorer2/${activiti.version}/activiti-webapp-explorer2-${activiti.version}.war" dest="${project.build.directory}/activiti-webapp-explorer2" />
<unzip src="${settings.localRepository}/org/activiti/activiti-webapp-explorer2/${activiti.version}/activiti-webapp-explorer2-${activiti.version}.war"
dest="${project.build.directory}/activiti-webapp-explorer2" />
<mkdir dir="${activiti-modeler.directory}" />
<copy file="${project.build.directory}/activiti-webapp-explorer2/modeler.html" todir="${activiti-modeler.directory}" />
<replace file="${activiti-modeler.directory}/modeler.html" token="&lt;/head&gt;" value="&lt;script type=&quot;text/javascript&quot;&gt;window.onunload = refreshParent; function refreshParent() { window.opener.location.reload(); }&lt;/script&gt;&lt;/head&gt;" />
<copy file="${project.build.directory}/activiti-webapp-explorer2/WEB-INF/classes/stencilset.json" todir="${activiti-modeler.directory}" />
<copy file="${project.build.directory}/activiti-webapp-explorer2/modeler.html"
todir="${activiti-modeler.directory}" />
<replace file="${activiti-modeler.directory}/modeler.html"
token="&lt;/head&gt;"
value="&lt;script type=&quot;text/javascript&quot;&gt;window.onunload = refreshParent; function refreshParent() { window.opener.location.reload(); }&lt;/script&gt;&lt;/head&gt;"/>
<copy file="${project.build.directory}/activiti-webapp-explorer2/WEB-INF/classes/stencilset.json"
todir="${activiti-modeler.directory}" />
<mkdir dir="${activiti-modeler.directory}/editor-app" />
<copy todir="${activiti-modeler.directory}/editor-app">
<fileset dir="${project.build.directory}/activiti-webapp-explorer2/editor-app" />
</copy>
<replaceregexp file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js" match="ORYX.CONFIG.ROOT_PATH =.*&quot;editor/&quot;; //TODO: Remove last slash!!" replace="BASE_PATH = window.location.toString().substr(0, window.location.toString().indexOf('/wicket')); ORYX.CONFIG.ROOT_PATH = BASE_PATH + &quot;/activiti-modeler/editor-app/editor/&quot;;" byline="true" />
<replace file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js" token="new Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(), {" value="new Ajax.Request(window.location.toString().substr(0, window.location.toString().indexOf('/activiti-modeler')) + &quot;/activiti-modeler/stencilset.json&quot;, {" />
<replace file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js" token="ORYX.Editor.createByUrl(modelUrl);" value="modelUrl = BASE_PATH + &quot;/workflowDefGET&quot;; ORYX.Editor.createByUrl(modelUrl);" />
<replace file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js" token="ORYX.Editor.createByUrl = function(modelUrl){" value="modelUrl = BASE_PATH + &quot;/workflowDefGET&quot;; ORYX.Editor.createByUrl = function(modelUrl){" />
<replace file="${activiti-modeler.directory}/editor-app/configuration/toolbar-default-actions.js" token="window.location.href = &quot;./&quot;;" value="window.close();" />
<replaceregexp file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js"
match="ORYX.CONFIG.ROOT_PATH =.*&quot;editor/&quot;; //TODO: Remove last slash!!"
replace="BASE_PATH = window.location.toString().substr(0, window.location.toString().indexOf(&#39;/wicket&#39;));
ORYX.CONFIG.ROOT_PATH = BASE_PATH + &quot;/activiti-modeler/editor-app/editor/&quot;;"
byline="true"/>
<replace file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js"
token="new Ajax.Request(ACTIVITI.CONFIG.contextRoot + &#39;/editor/stencilset?version=&#39; + Date.now(), {"
value="new Ajax.Request(window.location.toString().substr(0, window.location.toString().indexOf(&#39;/activiti-modeler&#39;)) + &quot;/activiti-modeler/stencilset.json&quot;, {"/>
<replace file="${activiti-modeler.directory}/editor-app/editor/oryx.debug.js"
token="ORYX.Editor.createByUrl(modelUrl);"
value="modelUrl = BASE_PATH + &quot;/workflowDefGET?modelId=&quot; + modelId; ORYX.Editor.createByUrl(modelUrl);" />
<replace file="${activiti-modeler.directory}/editor-app/configuration/toolbar-default-actions.js"
token="window.location.href = &quot;./&quot;;"
value="window.close();"/>
<copy file="${basedir}/src/main/resources/url-config.js" todir="${activiti-modeler.directory}/editor-app/configuration" overwrite="true" />
<copy file="${basedir}/src/main/resources/save-model.html" todir="${activiti-modeler.directory}/editor-app/popups" overwrite="true" />
<copy file="${basedir}/src/main/resources/url-config.js"
todir="${activiti-modeler.directory}/editor-app/configuration"
overwrite="true" />
<copy file="${basedir}/src/main/resources/save-model.html"
todir="${activiti-modeler.directory}/editor-app/popups"
overwrite="true" />
</target>
</configuration>
<goals>
......
......@@ -63,7 +63,7 @@ import org.springframework.util.ReflectionUtils;
public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyObjectRestClient> {
private static final long serialVersionUID = -1100228004207271271L;
private static final long serialVersionUID = -1100228004207271270L;
private static final String SERVICE_PROVIDER_ROLE = "Service provider";
......@@ -72,8 +72,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
// entitlements without which one coming from SERVICE ROLE
private final Set<String> entitlements = new HashSet<>();
protected AnyObjectDirectoryPanel(final String id, final AnyObjectDirectoryPanel.Builder builder,
final boolean wizardInModal) {
protected AnyObjectDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
super(id, builder, wizardInModal);
// ---------------------------
......@@ -203,8 +202,7 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
@Override
public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
final IModel<AnyWrapper<AnyObjectTO>> formModel = new CompoundPropertyModel<>(
new AnyWrapper<>(
model.getObject()));
new AnyWrapper<>(model.getObject()));
altDefaultModal.setFormModel(formModel);
target.add(altDefaultModal.setContent(new AnyStatusModal<>(
......
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# Copyright 2015 The CHOReVOLUTION project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
console.directory=${conf.directory}
version=${syncope.version}
site=${project.parent.url}
license=${licenseUrl}
anonymousUser=${anonymousUser}
anonymousKey=${anonymousKey}
......@@ -29,7 +27,10 @@ port=8080
rootPath=/syncope/rest/
useGZIPCompression=true
csrf=true
activitiModelerDirectory=${activiti-modeler.directory}
flowableModelerDirectory=${flowable-modeler.directory}
reconciliationReportKey=c3520ad9-179f-49e7-b315-d684d216dd97
......
......@@ -106,7 +106,7 @@ under the License.
<li wicket:id="topologyLI"><a href="#" wicket:id="topology"><i class="fa fa-plug"></i><span><wicket:message key="topology"/></span></a></li>
<li wicket:id="reportsLI"><a href="#" wicket:id="reports"><i class="fa fa-pie-chart"></i><span><wicket:message key="reports"/></span></a></li>
<li wicket:id="configurationLI" class="treeview">
<a href="#"><i class="fa fa-edit"></i><span><wicket:message key="configuration"/></span> <i class="fa fa-angle-left pull-right"></i></a>
<a href="#"><i class="fa fa-edit"></i><span><wicket:message key="configuration"/></span> <span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a>
<ul wicket:id="configurationUL" class="treeview-menu">
<li wicket:id="auditLI"><a href="#" wicket:id="audit"><i class="fa fa-check-square-o"></i><wicket:message key="audit"/></a></li>
<li wicket:id="logsLI"><a href="#" wicket:id="logs"><i class="fa fa-file-text-o"></i><wicket:message key="logs"/></a></li>
......@@ -120,7 +120,7 @@ under the License.
</ul>
</li>
<li wicket:id="extensionsLI" class="treeview">
<a href="#"><i class="fa fa-puzzle-piece"></i><span><wicket:message key="extensions"/></span> <i class="fa fa-angle-left pull-right"></i></a>
<a href="#"><i class="fa fa-puzzle-piece"></i><span><wicket:message key="extensions"/></span> <span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a>
<ul class="treeview-menu" wicket:id="extPages">
<li wicket:id="extPageLI">
<a href="#" wicket:id="extPage"><i wicket:id="extPageIcon"></i><span wicket:id="extPageLabel"/></a>
......@@ -216,9 +216,7 @@ under the License.
<div class="control-sidebar-bg" style="position: fixed; height: auto;"></div>
</div>
<div id="veil">
<img src="img/busy.gif"/>
</div>
<div id="veil">Loading...</div>
<script type="text/javascript">
$('.spanYear').html(new Date().getFullYear());
......
......@@ -21,7 +21,7 @@ var KISBPM = KISBPM || {};
KISBPM.URL = {
getModel: function (modelId) {
return window.location.toString().substr(0, window.location.toString().indexOf('/activiti-modeler'))
+ "/workflowDefGET";
+ "/workflowDefGET?modelId=" + modelId;
},
getStencilSet: function () {
return window.location.toString().substr(0, window.location.toString().indexOf('/activiti-modeler'))
......@@ -29,6 +29,6 @@ KISBPM.URL = {
},
putModel: function (modelId) {
return window.location.toString().substr(0, window.location.toString().indexOf('/activiti-modeler'))
+ "/workflowDefPUT";
+ "/workflowDefPUT?modelId=" + modelId;
}
};
#
#
# Copyright 2015 The CHOReVOLUTION project
#
# Licensed under the Apache License, Version 2.0 (the "License");
......@@ -17,7 +17,6 @@ console.directory=${conf.directory}
version=${syncope.version}
site=${project.parent.url}
license=${licenseUrl}
anonymousUser=${anonymousUser}
anonymousKey=${anonymousKey}
......@@ -26,7 +25,25 @@ scheme=http
host=localhost
port=9080
rootPath=/syncope/rest/
useGZIPCompression=true
csrf=true
activitiModelerDirectory=${activiti-modeler.directory}
flowableModelerDirectory=${flowable-modeler.directory}
reconciliationReportKey=c3520ad9-179f-49e7-b315-d684d216dd97
reconciliationReportKey=1
page.dashboard=org.apache.syncope.client.console.pages.Dashboard
page.realms=org.apache.syncope.client.console.pages.Realms
page.topology=org.apache.syncope.client.console.topology.Topology
page.reports=org.apache.syncope.client.console.pages.Reports
page.workflow=org.apache.syncope.client.console.pages.Workflow
page.audit=org.apache.syncope.client.console.pages.Audit
page.logs=org.apache.syncope.client.console.pages.Logs
page.securityquestions=org.apache.syncope.client.console.pages.SecurityQuestions
page.types=org.apache.syncope.client.console.pages.Types
page.roles=org.apache.syncope.client.console.pages.Roles
page.policies=org.apache.syncope.client.console.pages.Policies
page.notifications=org.apache.syncope.client.console.pages.Notifications
page.parameters=org.apache.syncope.client.console.pages.Parameters
......@@ -21,7 +21,7 @@ limitations under the License.
<classpath fallback="default">
<dir name="${basedir}/../console/target/classes">
</dir>
<dir name="${basedir}/../../ext/choreography/client-console/target/classes">
<dir name="${basedir}/../ext/choreography/client-console/target/classes">
</dir>
</classpath>
......@@ -31,7 +31,7 @@ limitations under the License.
</dir>
</link>
<link target="/">
<dir name="${basedir}/../../ext/choreography/client-console/target/classes">
<dir name="${basedir}/../ext/choreography/client-console/target/classes">
</dir>
</link>
</web>
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.syncope.core.persistence.jpa.dao;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.validation.ValidationException;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.ResourceCond;
import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
import org.apache.syncope.core.persistence.api.entity.PlainSchema;
import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;
@Repository
public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO {
private static final String EMPTY_QUERY = "SELECT any_id FROM user_search_attr WHERE 1=2";
@Autowired
private RealmDAO realmDAO;
@Autowired
private AnyObjectDAO anyObjectDAO;
@Autowired
private UserDAO userDAO;
@Autowired
private GroupDAO groupDAO;
@Autowired
private PlainSchemaDAO schemaDAO;
@Autowired
private AnyUtilsFactory anyUtilsFactory;
private String getAdminRealmsFilter(
final Set<String> adminRealms,
final SearchSupport svs,
final List<Object> parameters) {
Set<String> realmKeys = new HashSet<>();
for (String realmPath : RealmUtils.normalize(adminRealms)) {
Realm realm = realmDAO.findByFullPath(realmPath);
if (realm == null) {
LOG.warn("Ignoring invalid realm {}", realmPath);
} else {
CollectionUtils.collect(
realmDAO.findDescendants(realm), EntityUtils.<Realm>keyTransformer(), realmKeys);
}
}
StringBuilder adminRealmFilter = new StringBuilder().
append("SELECT any_id FROM ").append(svs.field().name).
append(" WHERE realm_id IN (SELECT id AS realm_id FROM Realm");
boolean firstRealm = true;
for (String realmKey : realmKeys) {
if (firstRealm) {
adminRealmFilter.append(" WHERE");
firstRealm = false;
} else {
adminRealmFilter.append(" OR");
}
adminRealmFilter.append(" id=?").append(setParameter(parameters, realmKey));
}
adminRealmFilter.append(')');
return adminRealmFilter.toString();
}
@Override
public int count(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind typeKind) {
List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
// 1. get the query string from the search condition
SearchSupport svs = new SearchSupport(typeKind);
StringBuilder queryString = getQuery(cond, parameters, svs);
// 2. take into account administrative realms
queryString.insert(0, "SELECT u.any_id FROM (");
queryString.append(") u WHERE any_id IN (");
queryString.append(getAdminRealmsFilter(adminRealms, svs, parameters)).append(')');
// 3. prepare the COUNT query
queryString.insert(0, "SELECT COUNT(any_id) FROM (");
queryString.append(") count_any_id");
Query countQuery = entityManager().createNativeQuery(queryString.toString());
fillWithParameters(countQuery, parameters);
return ((Number) countQuery.getSingleResult()).intValue();
}
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
@Override
public <T extends Any<?>> List<T> searchAssignable(final String realmFullPath, final AnyTypeKind kind) {
AssignableCond assignableCond = new AssignableCond();
assignableCond.setRealmFullPath(realmFullPath);
return search(SearchCond.getLeafCond(assignableCond), kind);
}
@Override
public <T extends Any<?>> List<T> search(final SearchCond cond, final AnyTypeKind typeKind) {
return search(cond, Collections.<OrderByClause>emptyList(), typeKind);
}
@Override
public <T extends Any<?>> List<T> search(
final SearchCond cond, final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
return search(SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, typeKind);
}
@Override
public <T extends Any<?>> List<T> search(
final Set<String> adminRealms, final SearchCond cond, final int page, final int itemsPerPage,
final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
List<T> result = Collections.<T>emptyList();
if (adminRealms != null && !adminRealms.isEmpty()) {
LOG.debug("Search condition:\n{}", cond);
if (cond != null && cond.isValid()) {
try {
result = doSearch(adminRealms, cond, page, itemsPerPage, orderBy, typeKind);
} catch (Exception e) {
LOG.error("While searching for {}", typeKind, e);
}
} else {
LOG.error("Invalid search condition:\n{}", cond);
}
}
return result;
}
@Override
public <T extends Any<?>> boolean matches(
final T any, final SearchCond cond, final AnyTypeKind typeKind) {
List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
// 1. get the query string from the search condition
SearchSupport svs = new SearchSupport(typeKind);
StringBuilder queryString = getQuery(cond, parameters, svs);
boolean matches;
if (queryString.length() == 0) {
// Could be empty: got into a group search with a single membership condition ...
matches = false;
} else {
// 2. take into account the passed user
queryString.insert(0, "SELECT u.any_id FROM (");
queryString.append(") u WHERE any_id=?").append(setParameter(parameters, any.getKey()));
// 3. prepare the search query
Query query = entityManager().createNativeQuery(queryString.toString());
// 4. populate the search query with parameter values
fillWithParameters(query, parameters);
// 5. executes query
matches = !query.getResultList().isEmpty();
}
return matches;
}
private int setParameter(final List<Object> parameters, final Object parameter) {
int key;
synchronized (parameters) {
parameters.add(parameter);
key = parameters.size();
}
return key;
}
private void fillWithParameters(final Query query, final List<Object> parameters) {
for (int i = 0; i < parameters.size(); i++) {
if (parameters.get(i) instanceof Date) {
query.setParameter(i + 1, (Date) parameters.get(i), TemporalType.TIMESTAMP);
} else if (parameters.get(i) instanceof Boolean) {
query.setParameter(i + 1, ((Boolean) parameters.get(i))
? 1
: 0);
} else {
query.setParameter(i + 1, parameters.get(i));
}
}
}
private StringBuilder buildSelect(final OrderBySupport orderBySupport) {
final StringBuilder select = new StringBuilder("SELECT u.any_id");
for (OrderBySupport.Item obs : orderBySupport.items) {
select.append(',').append(obs.select);
}
select.append(" FROM ");
return select;
}
private StringBuilder buildWhere(final OrderBySupport orderBySupport, final AnyTypeKind typeKind) {
SearchSupport svs = new SearchSupport(typeKind);
StringBuilder where = new StringBuilder(" u");
for (SearchSupport.SearchView searchView : orderBySupport.views) {
where.append(',');
if (searchView.name.equals(svs.attr().name)) {
where.append(" (SELECT * FROM ").append(searchView.name).append(" UNION ").
append("SELECT * FROM ").append(svs.nullAttr().name).append(')');
} else {
where.append(searchView.name);
}
where.append(' ').append(searchView.alias);
}
where.append(" WHERE ");
for (SearchSupport.SearchView searchView : orderBySupport.views) {
where.append("u.any_id=").append(searchView.alias).append(".any_id AND ");
}
for (OrderBySupport.Item obs : orderBySupport.items) {
if (StringUtils.isNotBlank(obs.where)) {
where.append(obs.where).append(" AND ");
}
}
where.append("u.any_id IN (");
return where;
}
private StringBuilder buildOrderBy(final OrderBySupport orderBySupport) {
StringBuilder orderBy = new StringBuilder();
for (OrderBySupport.Item obs : orderBySupport.items) {
orderBy.append(obs.orderBy).append(',');
}
if (!orderBySupport.items.isEmpty()) {
orderBy.insert(0, " ORDER BY ");
orderBy.deleteCharAt(orderBy.length() - 1);
}
return orderBy;
}
private OrderBySupport parseOrderBy(final AnyTypeKind type, final SearchSupport svs,
final List<OrderByClause> orderByClauses) {
final AnyUtils attrUtils = anyUtilsFactory.getInstance(type);
OrderBySupport orderBySupport = new OrderBySupport();
for (OrderByClause clause : orderByClauses) {
OrderBySupport.Item obs = new OrderBySupport.Item();
// Manage difference among external key attribute and internal JPA @Id
String fieldName = "key".equals(clause.getField()) ? "id" : clause.getField();
Field anyField = ReflectionUtils.findField(attrUtils.anyClass(), fieldName);
if (anyField ==<