mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-03 11:47:38 +08:00
PL-8127 Queries with scalars and aggregates from the client side
This commit is contained in:
parent
03f2185a3b
commit
2851052d6e
@ -20,6 +20,7 @@ package com.haulmont.cuba.client.sys;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.app.DataService;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -131,6 +132,11 @@ public class DataManagerClientImpl implements DataManager {
|
||||
commit(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
return dataService.loadValues(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataManager secure() {
|
||||
return this;
|
||||
|
@ -18,10 +18,7 @@
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.entity.AbstractNotPersistentEntity;
|
||||
import com.haulmont.cuba.core.entity.BaseEntityInternalAccess;
|
||||
import com.haulmont.cuba.core.entity.BaseGenericIdEntity;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.*;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import org.slf4j.Logger;
|
||||
@ -207,6 +204,12 @@ public class DataManagerBean implements DataManager {
|
||||
commit(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
DataStore store = storeFactory.get(context.getStoreName());
|
||||
return store.loadValues(context);
|
||||
}
|
||||
|
||||
protected boolean entityHasDynamicAttributes(Entity entity) {
|
||||
return entity instanceof BaseGenericIdEntity
|
||||
&& ((BaseGenericIdEntity) entity).getDynamicAttributes() != null;
|
||||
|
@ -17,9 +17,11 @@
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.CommitContext;
|
||||
import com.haulmont.cuba.core.global.DataManager;
|
||||
import com.haulmont.cuba.core.global.LoadContext;
|
||||
import com.haulmont.cuba.core.global.ValueLoadContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -53,4 +55,9 @@ public class DataServiceBean implements DataService {
|
||||
public long getCount(LoadContext<? extends Entity> context) {
|
||||
return dataManager.secure().getCount(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
return dataManager.secure().loadValues(context);
|
||||
}
|
||||
}
|
@ -140,8 +140,8 @@ public class DataServiceQueryBuilder {
|
||||
value = list;
|
||||
}
|
||||
|
||||
if (value instanceof LoadContext.Query.TemporalValue) {
|
||||
LoadContext.Query.TemporalValue temporalValue = (LoadContext.Query.TemporalValue) value;
|
||||
if (value instanceof TemporalValue) {
|
||||
TemporalValue temporalValue = (TemporalValue) value;
|
||||
query.setParameter(name, temporalValue.date, temporalValue.type);
|
||||
} else {
|
||||
query.setParameter(name, value);
|
||||
|
@ -17,8 +17,10 @@
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.CommitContext;
|
||||
import com.haulmont.cuba.core.global.LoadContext;
|
||||
import com.haulmont.cuba.core.global.ValueLoadContext;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
@ -54,4 +56,6 @@ public interface DataStore {
|
||||
* @return set of committed instances
|
||||
*/
|
||||
Set<Entity> commit(CommitContext context);
|
||||
|
||||
List<KeyValueEntity> loadValues(ValueLoadContext context);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.bali.util.Preconditions;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.chile.core.model.MetaProperty;
|
||||
import com.haulmont.chile.core.model.Session;
|
||||
@ -390,6 +391,60 @@ public class RdbmsStore implements DataStore {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
Preconditions.checkNotNullArgument(context, "context is null");
|
||||
Preconditions.checkNotNullArgument(context.getQuery(), "query is null");
|
||||
|
||||
ValueLoadContext.Query contextQuery = context.getQuery();
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("query: " + (DataServiceQueryBuilder.printQuery(contextQuery.getQueryString()))
|
||||
+ (contextQuery.getFirstResult() == 0 ? "" : ", first=" + contextQuery.getFirstResult())
|
||||
+ (contextQuery.getMaxResults() == 0 ? "" : ", max=" + contextQuery.getMaxResults()));
|
||||
|
||||
List<KeyValueEntity> entities = new ArrayList<>();
|
||||
|
||||
try (Transaction tx = persistence.createTransaction(storeName)) {
|
||||
EntityManager em = persistence.getEntityManager(storeName);
|
||||
em.setSoftDeletion(context.isSoftDeletion());
|
||||
|
||||
List<String> keys = context.getProperties();
|
||||
|
||||
DataServiceQueryBuilder queryBuilder = AppBeans.get(DataServiceQueryBuilder.NAME);
|
||||
queryBuilder.init(contextQuery.getQueryString(), contextQuery.getParameters(), null, metadata.getClassNN(KeyValueEntity.class).getName());
|
||||
Query query = queryBuilder.getQuery(em);
|
||||
|
||||
if (contextQuery.getFirstResult() != 0)
|
||||
query.setFirstResult(contextQuery.getFirstResult());
|
||||
if (contextQuery.getMaxResults() != 0)
|
||||
query.setMaxResults(contextQuery.getMaxResults());
|
||||
|
||||
List resultList = query.getResultList();
|
||||
for (Object item : resultList) {
|
||||
KeyValueEntity entity = new KeyValueEntity();
|
||||
entity.setIdName(context.getIdName());
|
||||
entities.add(entity);
|
||||
|
||||
if (item instanceof Object[]) {
|
||||
Object[] row = (Object[]) item;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
if (row.length > i) {
|
||||
entity.setValue(key, row[i]);
|
||||
}
|
||||
}
|
||||
} else if (!keys.isEmpty()) {
|
||||
entity.setValue(keys.get(0), item);
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
protected View getViewFromContext(CommitContext context, Entity entity) {
|
||||
View view = context.getViews().get(entity);
|
||||
if (view == null) {
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core;
|
||||
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.AppBeans;
|
||||
import com.haulmont.cuba.core.global.DataManager;
|
||||
import com.haulmont.cuba.core.global.ValueLoadContext;
|
||||
import com.haulmont.cuba.testsupport.TestContainer;
|
||||
import com.haulmont.cuba.testsupport.TestSupport;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NonEntityQueryTest {
|
||||
|
||||
@ClassRule
|
||||
public static TestContainer cont = TestContainer.Common.INSTANCE;
|
||||
|
||||
private DataManager dataManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
dataManager = AppBeans.get(DataManager.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalars() throws Exception {
|
||||
ValueLoadContext context = ValueLoadContext.create()
|
||||
.setQuery(ValueLoadContext.createQuery("select u.id, u.login from sec$User u where u.id = :id1 or u.id = :id2 order by u.login")
|
||||
.setParameter("id1", TestSupport.ADMIN_USER_ID)
|
||||
.setParameter("id2", TestSupport.ANONYMOUS_USER_ID))
|
||||
.addProperty("userId").addProperty("login");
|
||||
|
||||
List<KeyValueEntity> list = dataManager.loadValues(context);
|
||||
|
||||
assertEquals(2, list.size());
|
||||
KeyValueEntity e = list.get(0);
|
||||
assertEquals(TestSupport.ADMIN_USER_ID, e.getValue("userId"));
|
||||
assertEquals("admin", e.getValue("login"));
|
||||
e = list.get(1);
|
||||
assertEquals(TestSupport.ANONYMOUS_USER_ID, e.getValue("userId"));
|
||||
assertEquals("anonymous", e.getValue("login"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregates() throws Exception {
|
||||
ValueLoadContext context = ValueLoadContext.create();
|
||||
ValueLoadContext.Query query = context.setQueryString("select count(u) from sec$User u where u.id = :id1 or u.id = :id2");
|
||||
query.setParameter("id1", TestSupport.ADMIN_USER_ID);
|
||||
query.setParameter("id2", TestSupport.ANONYMOUS_USER_ID);
|
||||
context.addProperty("count");
|
||||
|
||||
List<KeyValueEntity> list = dataManager.loadValues(context);
|
||||
|
||||
assertEquals(1, list.size());
|
||||
KeyValueEntity e = list.get(0);
|
||||
assertEquals(Long.valueOf(2), e.getValue("count"));
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ public class QueryFilter2Test {
|
||||
@Test
|
||||
public void testParse() throws Exception {
|
||||
Element element = Dom4j.readDocument(xml).getRootElement();
|
||||
QueryFilter queryFilter = new QueryFilter(element, "sec$User");
|
||||
QueryFilter queryFilter = new QueryFilter(element);
|
||||
|
||||
Condition root = queryFilter.getRoot();
|
||||
System.out.println(new GroovyGenerator().generateGroovy(root));
|
||||
|
@ -55,7 +55,7 @@ public class QueryFilterTest {
|
||||
private QueryFilter createFilter(String name) {
|
||||
InputStream stream = QueryFilterTest.class.getResourceAsStream("/com/haulmont/cuba/core/global/filter/" + name);
|
||||
Document doc = Dom4j.readDocument(stream);
|
||||
return new QueryFilter(doc.getRootElement(), "saneco$GenDoc");
|
||||
return new QueryFilter(doc.getRootElement());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -29,6 +29,8 @@ public class TestSupport {
|
||||
|
||||
public static final UUID ADMIN_USER_ID = UUID.fromString("60885987-1b61-4247-94c7-dff348347f93");
|
||||
|
||||
public static final UUID ANONYMOUS_USER_ID = UUID.fromString("a405db59-e674-4f63-8afe-269dda788fe8");
|
||||
|
||||
public static final UUID COMPANY_GROUP_ID = UUID.fromString("0fa2b1a5-1d68-4d69-9fbd-dff348347f93");
|
||||
|
||||
public static final UUID ADMIN_ROLE_ID = UUID.fromString("0c018061-b26f-4de2-a5be-dff348347f93");
|
||||
|
@ -17,8 +17,10 @@
|
||||
package com.haulmont.cuba.core.app;
|
||||
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.CommitContext;
|
||||
import com.haulmont.cuba.core.global.LoadContext;
|
||||
import com.haulmont.cuba.core.global.ValueLoadContext;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
@ -65,4 +67,6 @@ public interface DataService {
|
||||
* @return number of instances in the database
|
||||
*/
|
||||
long getCount(LoadContext<? extends Entity> context);
|
||||
|
||||
List<KeyValueEntity> loadValues(ValueLoadContext context);
|
||||
}
|
||||
|
@ -42,6 +42,10 @@ public class KeyValueMetaClass extends MetadataObjectImpl implements MetaClass {
|
||||
properties.remove(propertyName);
|
||||
}
|
||||
|
||||
public KeyValueMetaClass() {
|
||||
name = "sys$KeyValueEntity";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MetaClass getAncestor() {
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package com.haulmont.cuba.core.app.keyvalue;
|
||||
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.datatypes.Datatypes;
|
||||
import com.haulmont.chile.core.model.*;
|
||||
import com.haulmont.chile.core.model.impl.ClassRange;
|
||||
@ -62,6 +63,16 @@ public class KeyValueMetaProperty extends MetadataObjectImpl implements MetaProp
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValueMetaProperty(MetaClass metaClass, String name, Datatype datatype) {
|
||||
this.name = name;
|
||||
this.javaClass = datatype.getJavaClass();
|
||||
this.metaClass = metaClass;
|
||||
this.mandatory = false;
|
||||
|
||||
this.range = new DatatypeRange(datatype);
|
||||
this.type = Type.DATATYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaModel getModel() {
|
||||
return metaClass.getModel();
|
||||
|
@ -18,12 +18,16 @@
|
||||
package com.haulmont.cuba.core.entity;
|
||||
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.chile.core.model.impl.AbstractInstance;
|
||||
import com.haulmont.cuba.core.entity.annotation.SystemLevel;
|
||||
import com.haulmont.cuba.core.global.UuidProvider;
|
||||
import com.haulmont.cuba.core.sys.CubaEnhancingDisabled;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Entity that contains a variable set of attributes. For example:
|
||||
@ -41,11 +45,21 @@ import java.util.Map;
|
||||
*/
|
||||
@com.haulmont.chile.core.annotations.MetaClass(name = "sys$KeyValueEntity")
|
||||
@SystemLevel
|
||||
public class KeyValueEntity extends AbstractNotPersistentEntity implements CubaEnhancingDisabled {
|
||||
public class KeyValueEntity
|
||||
extends AbstractInstance
|
||||
implements Entity<Object>, CubaEnhancingDisabled {
|
||||
|
||||
private Map<String, Object> properties = new LinkedHashMap<>();
|
||||
protected UUID uuid;
|
||||
|
||||
private MetaClass metaClass;
|
||||
protected Map<String, Object> properties = new LinkedHashMap<>();
|
||||
|
||||
protected String idName;
|
||||
|
||||
protected MetaClass metaClass;
|
||||
|
||||
public KeyValueEntity() {
|
||||
uuid = UuidProvider.createUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaClass getMetaClass() {
|
||||
@ -58,6 +72,14 @@ public class KeyValueEntity extends AbstractNotPersistentEntity implements CubaE
|
||||
this.metaClass = metaClass;
|
||||
}
|
||||
|
||||
public String getIdName() {
|
||||
return idName;
|
||||
}
|
||||
|
||||
public void setIdName(String idName) {
|
||||
this.idName = idName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getValue(String name) {
|
||||
//noinspection unchecked
|
||||
@ -72,4 +94,51 @@ public class KeyValueEntity extends AbstractNotPersistentEntity implements CubaE
|
||||
propertyChanged(name, oldValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getId() {
|
||||
if (idName == null)
|
||||
return uuid;
|
||||
else
|
||||
return properties.get(idName);
|
||||
}
|
||||
|
||||
public void setId(Object id) {
|
||||
if (idName == null)
|
||||
throw new IllegalStateException("Id name is not set");
|
||||
properties.put(idName, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
KeyValueEntity that = (KeyValueEntity) o;
|
||||
Object id = getId();
|
||||
Object thatId = that.getId();
|
||||
|
||||
if (id != null && thatId != null)
|
||||
return id.equals(thatId);
|
||||
|
||||
return Objects.equals(uuid, that.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
Object id = getId();
|
||||
if (id != null)
|
||||
return id.hashCode();
|
||||
return uuid.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Object id = null;
|
||||
if (idName != null)
|
||||
id = properties.get(idName);
|
||||
if (id == null)
|
||||
id = "?(" + uuid + ")";
|
||||
return "sys$KeyValueEntity-" + id;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
public interface DataLoadContext {
|
||||
|
||||
DataLoadContextQuery setQueryString(String queryString);
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
public interface DataLoadContextQuery {
|
||||
|
||||
DataLoadContextQuery setParameter(String name, Object value);
|
||||
|
||||
DataLoadContextQuery setParameter(String name, Date value, TemporalType temporalType);
|
||||
|
||||
Map<String, Object> getParameters();
|
||||
DataLoadContextQuery setParameters(Map<String, Object> parameters);
|
||||
|
||||
int getFirstResult();
|
||||
DataLoadContextQuery setFirstResult(int firstResult);
|
||||
|
||||
int getMaxResults();
|
||||
DataLoadContextQuery setMaxResults(int maxResults);
|
||||
}
|
@ -19,6 +19,7 @@ package com.haulmont.cuba.core.global;
|
||||
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
@ -142,6 +143,8 @@ public interface DataManager {
|
||||
*/
|
||||
void remove(Entity entity);
|
||||
|
||||
List<KeyValueEntity> loadValues(ValueLoadContext context);
|
||||
|
||||
/**
|
||||
* Returns the DataManager implementation that is guaranteed to apply security restrictions.
|
||||
* <p>By default, DataManager does not apply security when used on the middleware. Use this method if you want
|
||||
|
@ -37,7 +37,7 @@ import java.util.stream.Collectors;
|
||||
List<User> users = dataManager.loadList(context);
|
||||
* </pre>
|
||||
*/
|
||||
public class LoadContext<E extends Entity> implements Serializable {
|
||||
public class LoadContext<E extends Entity> implements DataLoadContext, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8808320502197308698L;
|
||||
|
||||
@ -118,6 +118,7 @@ public class LoadContext<E extends Entity> implements Serializable {
|
||||
* @param queryString JPQL query string. Only named parameters are supported.
|
||||
* @return query definition object
|
||||
*/
|
||||
@Override
|
||||
public Query setQueryString(String queryString) {
|
||||
final Query query = new Query(queryString);
|
||||
setQuery(query);
|
||||
@ -283,7 +284,7 @@ public class LoadContext<E extends Entity> implements Serializable {
|
||||
/**
|
||||
* Class that defines a query to be executed for data loading.
|
||||
*/
|
||||
public static class Query implements Serializable {
|
||||
public static class Query implements DataLoadContextQuery, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3819951144050635838L;
|
||||
|
||||
@ -293,18 +294,6 @@ public class LoadContext<E extends Entity> implements Serializable {
|
||||
private int maxResults;
|
||||
private boolean cacheable;
|
||||
|
||||
public static class TemporalValue implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4972088045550018312L;
|
||||
|
||||
public final Date date;
|
||||
public final TemporalType type;
|
||||
|
||||
public TemporalValue(Date date, TemporalType type) {
|
||||
this.date = date;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param queryString JPQL query string. Only named parameters are supported.
|
||||
*/
|
||||
@ -359,8 +348,9 @@ public class LoadContext<E extends Entity> implements Serializable {
|
||||
/**
|
||||
* @param parameters map of the query parameters
|
||||
*/
|
||||
public void setParameters(Map<String, Object> parameters) {
|
||||
public Query setParameters(Map<String, Object> parameters) {
|
||||
this.parameters.putAll(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
public class TemporalValue implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4972088045550018312L;
|
||||
|
||||
public final Date date;
|
||||
public final TemporalType type;
|
||||
|
||||
public TemporalValue(Date date, TemporalType type) {
|
||||
this.date = date;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.core.global;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
public class ValueLoadContext implements DataLoadContext, Serializable {
|
||||
|
||||
protected String storeName = Stores.MAIN;
|
||||
protected Query query;
|
||||
protected boolean softDeletion = true;
|
||||
protected String idName;
|
||||
protected List<String> properties = new ArrayList<>();
|
||||
|
||||
public static ValueLoadContext create() {
|
||||
return new ValueLoadContext();
|
||||
}
|
||||
|
||||
public static Query createQuery(String queryString) {
|
||||
return new Query(queryString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query setQueryString(String queryString) {
|
||||
query = new Query(queryString);
|
||||
return query;
|
||||
}
|
||||
|
||||
public String getStoreName() {
|
||||
return storeName;
|
||||
}
|
||||
|
||||
public ValueLoadContext setStoreName(String storeName) {
|
||||
this.storeName = storeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueLoadContext setQuery(Query query) {
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Query getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public ValueLoadContext setSoftDeletion(boolean softDeletion) {
|
||||
this.softDeletion = softDeletion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isSoftDeletion() {
|
||||
return softDeletion;
|
||||
}
|
||||
|
||||
public String getIdName() {
|
||||
return idName;
|
||||
}
|
||||
|
||||
public void setIdName(String idName) {
|
||||
this.idName = idName;
|
||||
}
|
||||
|
||||
public ValueLoadContext addProperty(String name) {
|
||||
properties.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueLoadContext setProperties(List<String> properties) {
|
||||
this.properties.clear();
|
||||
this.properties.addAll(properties);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ValuesContext{query=%s, softDeletion=%s, keys=%s}", query, softDeletion, properties);
|
||||
}
|
||||
|
||||
public static class Query implements DataLoadContextQuery, Serializable {
|
||||
|
||||
private String queryString;
|
||||
private int firstResult;
|
||||
private int maxResults;
|
||||
private Map<String, Object> parameters = new HashMap<>();
|
||||
|
||||
/**
|
||||
* @param queryString JPQL query string. Only named parameters are supported.
|
||||
*/
|
||||
public Query(String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JPQL query string
|
||||
*/
|
||||
public String getQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param queryString JPQL query string. Only named parameters are supported.
|
||||
*/
|
||||
public void setQueryString(String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value for a query parameter.
|
||||
* @param name parameter name
|
||||
* @param value parameter value
|
||||
* @return this query instance for chaining
|
||||
*/
|
||||
public Query setParameter(String name, Object value) {
|
||||
parameters.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value for a parameter of java.util.Date type.
|
||||
* @param name parameter name
|
||||
* @param value date value
|
||||
* @param temporalType temporal type
|
||||
* @return this query instance for chaining
|
||||
*/
|
||||
public Query setParameter(String name, Date value, TemporalType temporalType) {
|
||||
parameters.put(name, new TemporalValue(value, temporalType));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return editable map of the query parameters
|
||||
*/
|
||||
public Map<String, Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameters map of the query parameters
|
||||
*/
|
||||
public Query setParameters(Map<String, Object> parameters) {
|
||||
this.parameters.putAll(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param firstResult results offset
|
||||
* @return this query instance for chaining
|
||||
*/
|
||||
public Query setFirstResult(int firstResult) {
|
||||
this.firstResult = firstResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxResults results limit
|
||||
* @return this query instance for chaining
|
||||
*/
|
||||
public Query setMaxResults(int maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return results offset
|
||||
*/
|
||||
public int getFirstResult() {
|
||||
return firstResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return results limit
|
||||
*/
|
||||
public int getMaxResults() {
|
||||
return maxResults;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Query{" +
|
||||
"queryString='" + queryString + '\'' +
|
||||
", firstResult=" + firstResult +
|
||||
", maxResults=" + maxResults +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
@ -26,31 +26,24 @@ import org.dom4j.Element;
|
||||
import java.util.*;
|
||||
|
||||
public class QueryFilter extends FilterParser {
|
||||
private final String targetEntity;
|
||||
|
||||
public QueryFilter(Condition condition, String targetEntity) {
|
||||
public QueryFilter(Condition condition) {
|
||||
super(condition);
|
||||
this.targetEntity = targetEntity;
|
||||
}
|
||||
|
||||
public QueryFilter(Element element, String targetEntity) {
|
||||
public QueryFilter(Element element) {
|
||||
super(element);
|
||||
this.targetEntity = targetEntity;
|
||||
}
|
||||
|
||||
public static QueryFilter merge(QueryFilter src1, QueryFilter src2) {
|
||||
if (src1 == null || src2 == null)
|
||||
throw new IllegalArgumentException("Source query filter is null");
|
||||
|
||||
if (!src1.targetEntity.equals(src2.targetEntity))
|
||||
throw new IllegalArgumentException("Target entities do not match");
|
||||
|
||||
|
||||
Condition root = new LogicalCondition("root", LogicalOp.AND);
|
||||
root.getConditions().add(src1.getRoot());
|
||||
root.getConditions().add(src2.getRoot());
|
||||
|
||||
QueryFilter queryFilter = new QueryFilter(root, src1.targetEntity);
|
||||
QueryFilter queryFilter = new QueryFilter(root);
|
||||
return queryFilter;
|
||||
}
|
||||
|
||||
|
@ -1246,7 +1246,7 @@ public class FilterDelegateImpl implements FilterDelegate {
|
||||
|
||||
if (getResultingManualApplyRequired()) {
|
||||
// set initial denying condition to get empty datasource before explicit filter applying
|
||||
QueryFilter queryFilter = new QueryFilter(new DenyingClause(), datasource.getMetaClass().getName());
|
||||
QueryFilter queryFilter = new QueryFilter(new DenyingClause());
|
||||
if (dsQueryFilter != null) {
|
||||
queryFilter = QueryFilter.merge(dsQueryFilter, queryFilter);
|
||||
}
|
||||
@ -1471,7 +1471,7 @@ public class FilterDelegateImpl implements FilterDelegate {
|
||||
|
||||
if (!Strings.isNullOrEmpty(currentFilterXml)) {
|
||||
Element element = Dom4j.readDocument(currentFilterXml).getRootElement();
|
||||
QueryFilter queryFilter = new QueryFilter(element, datasource.getMetaClass().getName());
|
||||
QueryFilter queryFilter = new QueryFilter(element);
|
||||
|
||||
if (dsQueryFilter != null) {
|
||||
queryFilter = QueryFilter.merge(dsQueryFilter, queryFilter);
|
||||
|
@ -433,7 +433,7 @@ public class DsBuilder {
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public RuntimePropsDatasource buildRuntimePropsDataSource(String mainDsId, @Nullable MetaClass categorizedEntityClass) {
|
||||
public RuntimePropsDatasource buildRuntimePropsDatasource(String mainDsId, @Nullable MetaClass categorizedEntityClass) {
|
||||
init();
|
||||
RuntimePropsDatasourceImpl datasource;
|
||||
datasource = new RuntimePropsDatasourceImpl(dsContext, dataSupplier, id, mainDsId, categorizedEntityClass);
|
||||
@ -441,6 +441,36 @@ public class DsBuilder {
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public ValueCollectionDatasourceImpl buildValuesCollectionDatasource() {
|
||||
ValueCollectionDatasourceImpl datasource = new ValueCollectionDatasourceImpl();
|
||||
datasource.setup(dsContext, dataSupplier, id, metaClass, null);
|
||||
if (maxResults > 0)
|
||||
datasource.setMaxResults(maxResults);
|
||||
datasource.setSoftDeletion(softDeletion);
|
||||
registerDatasource(datasource);
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public ValueGroupDatasourceImpl buildValuesGroupDatasource() {
|
||||
ValueGroupDatasourceImpl datasource = new ValueGroupDatasourceImpl();
|
||||
datasource.setup(dsContext, dataSupplier, id, metaClass, null);
|
||||
if (maxResults > 0)
|
||||
datasource.setMaxResults(maxResults);
|
||||
datasource.setSoftDeletion(softDeletion);
|
||||
registerDatasource(datasource);
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public ValueHierarchicalDatasourceImpl buildValuesHierarchicalDatasourceImpl() {
|
||||
ValueHierarchicalDatasourceImpl datasource = new ValueHierarchicalDatasourceImpl();
|
||||
datasource.setup(dsContext, dataSupplier, id, metaClass, null);
|
||||
if (maxResults > 0)
|
||||
datasource.setMaxResults(maxResults);
|
||||
datasource.setSoftDeletion(softDeletion);
|
||||
registerDatasource(datasource);
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private void registerDatasource(Datasource datasource) {
|
||||
if (dsContext != null && id != null) {
|
||||
((DsContextImplementation) dsContext).register(datasource);
|
||||
|
@ -494,8 +494,8 @@ public abstract class AbstractCollectionDatasource<T extends Entity<K>, K>
|
||||
}
|
||||
}
|
||||
|
||||
protected LoadContext.Query createLoadContextQuery(LoadContext context, Map<String, Object> params) {
|
||||
LoadContext.Query q;
|
||||
protected DataLoadContextQuery createDataQuery(DataLoadContext context, Map<String, Object> params) {
|
||||
DataLoadContextQuery q = null;
|
||||
if (query != null && queryParameters != null) {
|
||||
Map<String, Object> parameters = getQueryParameters(params);
|
||||
for (ParameterInfo info : queryParameters) {
|
||||
@ -532,7 +532,7 @@ public abstract class AbstractCollectionDatasource<T extends Entity<K>, K>
|
||||
if (paramNames.contains(entry.getKey()))
|
||||
q.setParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
} else {
|
||||
} else if (!(context instanceof ValueLoadContext)) {
|
||||
Collection<MetaProperty> properties = metadata.getTools().getNamePatternProperties(metaClass);
|
||||
if (!properties.isEmpty()) {
|
||||
StringBuilder orderBy = new StringBuilder();
|
||||
@ -550,8 +550,8 @@ public abstract class AbstractCollectionDatasource<T extends Entity<K>, K>
|
||||
} else
|
||||
q = context.setQueryString("select e from " + metaClass.getName() + " e");
|
||||
}
|
||||
if (q != null) {
|
||||
q.setCacheable(isCacheable());
|
||||
if (q instanceof LoadContext.Query) {
|
||||
((LoadContext.Query) q).setCacheable(isCacheable());
|
||||
}
|
||||
return q;
|
||||
}
|
||||
@ -563,7 +563,7 @@ public abstract class AbstractCollectionDatasource<T extends Entity<K>, K>
|
||||
*/
|
||||
public int getCount() {
|
||||
LoadContext<Entity> context = new LoadContext<>(metaClass);
|
||||
LoadContext.Query q = createLoadContextQuery(context, savedParameters == null ? Collections.<String, Object>emptyMap() : savedParameters);
|
||||
LoadContext.Query q = (LoadContext.Query) createDataQuery(context, savedParameters == null ? Collections.<String, Object>emptyMap() : savedParameters);
|
||||
context.setSoftDeletion(isSoftDeletion());
|
||||
if (q == null)
|
||||
return 0;
|
||||
|
@ -499,7 +499,7 @@ public class CollectionDatasourceImpl<T extends Entity<K>, K>
|
||||
params = Collections.emptyMap();
|
||||
} else
|
||||
params = savedParameters;
|
||||
LoadContext.Query q = createLoadContextQuery(context, params);
|
||||
LoadContext.Query q = (LoadContext.Query) createDataQuery(context, params);
|
||||
if (sortInfos != null && sortOnDb) {
|
||||
setSortDirection(q);
|
||||
}
|
||||
@ -552,7 +552,7 @@ public class CollectionDatasourceImpl<T extends Entity<K>, K>
|
||||
protected LoadContext beforeLoadData(Map<String, Object> params) {
|
||||
final LoadContext context = new LoadContext(metaClass);
|
||||
|
||||
LoadContext.Query q = createLoadContextQuery(context, params);
|
||||
LoadContext.Query q = (LoadContext.Query) createDataQuery(context, params);
|
||||
if (q == null) {
|
||||
detachListener(data.values());
|
||||
data.clear();
|
||||
|
@ -18,6 +18,7 @@ package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.gui.data.DataSupplier;
|
||||
|
||||
@ -78,6 +79,11 @@ public class GenericDataSupplier implements DataSupplier {
|
||||
dataManager.remove(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
return dataManager.loadValues(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataManager secure() {
|
||||
return dataManager;
|
||||
|
@ -42,18 +42,18 @@ public class HierarchicalDatasourceImpl<T extends Entity<K>, K>
|
||||
@Override
|
||||
public Collection<K> getChildren(K itemId) {
|
||||
if (hierarchyPropertyName != null) {
|
||||
final Entity item = getItem(itemId);
|
||||
if (item == null)
|
||||
final Entity currentItem = getItem(itemId);
|
||||
if (currentItem == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
List<K> res = new ArrayList<>();
|
||||
|
||||
Collection<K> ids = getItemIds();
|
||||
for (K id : ids) {
|
||||
Entity<K> currentItem = getItem(id);
|
||||
Object parentItem = currentItem.getValue(hierarchyPropertyName);
|
||||
if (parentItem != null && parentItem.equals(item))
|
||||
res.add(currentItem.getId());
|
||||
Entity<K> item = getItemNN(id);
|
||||
Entity<K> parentItem = item.getValue(hierarchyPropertyName);
|
||||
if (parentItem != null && parentItem.getId().equals(itemId))
|
||||
res.add(item.getId());
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -68,8 +68,8 @@ public class HierarchicalDatasourceImpl<T extends Entity<K>, K>
|
||||
if (item == null)
|
||||
return null;
|
||||
else {
|
||||
Entity<K> value = item.getValue(hierarchyPropertyName);
|
||||
return value == null ? null : value.getId();
|
||||
Entity<K> parentItem = item.getValue(hierarchyPropertyName);
|
||||
return parentItem == null ? null : parentItem.getId();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -83,8 +83,8 @@ public class HierarchicalDatasourceImpl<T extends Entity<K>, K>
|
||||
Set<K> result = new LinkedHashSet<>();
|
||||
for (K id : ids) {
|
||||
Entity<K> item = getItemNN(id);
|
||||
Object value = item.getValue(hierarchyPropertyName);
|
||||
if (value == null || !containsItem(((T) value).getId()))
|
||||
Entity<K> parentItem = item.getValue(hierarchyPropertyName);
|
||||
if (parentItem == null || !containsItem(parentItem.getId()))
|
||||
result.add(item.getId());
|
||||
}
|
||||
return result;
|
||||
@ -99,8 +99,8 @@ public class HierarchicalDatasourceImpl<T extends Entity<K>, K>
|
||||
if (item == null) return false;
|
||||
|
||||
if (hierarchyPropertyName != null) {
|
||||
Object value = item.getValue(hierarchyPropertyName);
|
||||
return (value == null || !containsItem(((T) value).getId()));
|
||||
Entity<K> parentItem = item.getValue(hierarchyPropertyName);
|
||||
return (parentItem == null || !containsItem(parentItem.getId()));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@ -108,15 +108,16 @@ public class HierarchicalDatasourceImpl<T extends Entity<K>, K>
|
||||
|
||||
@Override
|
||||
public boolean hasChildren(K itemId) {
|
||||
final Entity item = getItem(itemId);
|
||||
if (item == null) return false;
|
||||
final Entity currentItem = getItem(itemId);
|
||||
if (currentItem == null)
|
||||
return false;
|
||||
|
||||
if (hierarchyPropertyName != null) {
|
||||
Collection<K> ids = getItemIds();
|
||||
for (K id : ids) {
|
||||
Entity currentItem = getItem(id);
|
||||
Object parentItem = currentItem.getValue(hierarchyPropertyName);
|
||||
if (parentItem != null && parentItem.equals(item))
|
||||
Entity item = getItemNN(id);
|
||||
Entity parentItem = item.getValue(hierarchyPropertyName);
|
||||
if (parentItem != null && parentItem.getId().equals(itemId))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -17,23 +17,34 @@
|
||||
|
||||
package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaProperty;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.View;
|
||||
import com.haulmont.cuba.gui.data.CollectionDatasource;
|
||||
import com.haulmont.cuba.gui.data.DataSupplier;
|
||||
import com.haulmont.cuba.gui.data.DsContext;
|
||||
import com.haulmont.cuba.gui.logging.UIPerformanceLogger;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.perf4j.StopWatch;
|
||||
import org.perf4j.log4j.Log4JStopWatch;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link CollectionDatasource} that supports {@link KeyValueEntity}.
|
||||
*/
|
||||
public class KeyValueCollectionDatasourceImpl extends CollectionDatasourceImpl<KeyValueEntity, UUID>{
|
||||
public class ValueCollectionDatasourceImpl
|
||||
extends CollectionDatasourceImpl<KeyValueEntity, Object>
|
||||
implements ValueDatasource {
|
||||
|
||||
protected final ValueDatasourceDelegate delegate;
|
||||
|
||||
public ValueCollectionDatasourceImpl() {
|
||||
delegate = new ValueDatasourceDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(DsContext dsContext, DataSupplier dataSupplier, String id, MetaClass metaClass, @Nullable View view) {
|
||||
@ -43,13 +54,35 @@ public class KeyValueCollectionDatasourceImpl extends CollectionDatasourceImpl<K
|
||||
this.metaClass = new KeyValueMetaClass();
|
||||
}
|
||||
|
||||
public KeyValueCollectionDatasourceImpl addProperty(String name) {
|
||||
((KeyValueMetaClass) metaClass).addProperty(new KeyValueMetaProperty(metaClass, name, String.class));
|
||||
@Override
|
||||
public ValueCollectionDatasourceImpl setIdName(String name) {
|
||||
delegate.setIdName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueCollectionDatasourceImpl addProperty(String name) {
|
||||
delegate.addProperty(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueCollectionDatasourceImpl addProperty(String name, Class aClass) {
|
||||
delegate.addProperty(name, aClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueCollectionDatasourceImpl addProperty(String name, Datatype type) {
|
||||
delegate.addProperty(name, type);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadData(Map<String, Object> params) {
|
||||
String tag = getLoggingTag("VDS");
|
||||
StopWatch sw = new Log4JStopWatch(tag, Logger.getLogger(UIPerformanceLogger.class));
|
||||
|
||||
delegate.loadData(params);
|
||||
|
||||
sw.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,4 +96,8 @@ public class KeyValueCollectionDatasourceImpl extends CollectionDatasourceImpl<K
|
||||
super.addItem(item);
|
||||
item.setMetaClass(metaClass);
|
||||
}
|
||||
|
||||
public void setStoreName(String storeName) {
|
||||
this.delegate.setStoreName(storeName);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
|
||||
public interface ValueDatasource {
|
||||
|
||||
MetaClass getMetaClass();
|
||||
|
||||
ValueDatasource setIdName(String name);
|
||||
|
||||
ValueDatasource addProperty(String name);
|
||||
|
||||
ValueDatasource addProperty(String name, Class aClass);
|
||||
|
||||
ValueDatasource addProperty(String name, Datatype type);
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 Haulmont.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.bali.util.Preconditions;
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.model.MetaProperty;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaProperty;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.ValueLoadContext;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ValueDatasourceDelegate {
|
||||
|
||||
private String storeName;
|
||||
|
||||
private String idName;
|
||||
|
||||
protected CollectionDatasourceImpl ds;
|
||||
|
||||
public ValueDatasourceDelegate(CollectionDatasourceImpl datasource) {
|
||||
this.ds = datasource;
|
||||
}
|
||||
|
||||
public String getStoreName() {
|
||||
return storeName;
|
||||
}
|
||||
|
||||
public void setStoreName(String storeName) {
|
||||
this.storeName = storeName;
|
||||
}
|
||||
|
||||
public void setIdName(String name) {
|
||||
this.idName = name;
|
||||
}
|
||||
|
||||
public void addProperty(String name) {
|
||||
Preconditions.checkNotNullArgument(name, "name is null");
|
||||
((KeyValueMetaClass) ds.metaClass).addProperty(new KeyValueMetaProperty(ds.metaClass, name, String.class));
|
||||
}
|
||||
|
||||
public void addProperty(String name, Class type) {
|
||||
Preconditions.checkNotNullArgument(name, "name is null");
|
||||
Preconditions.checkNotNullArgument(name, "type is null");
|
||||
((KeyValueMetaClass) ds.metaClass).addProperty(new KeyValueMetaProperty(ds.metaClass, name, type));
|
||||
}
|
||||
|
||||
public void addProperty(String name, Datatype type) {
|
||||
Preconditions.checkNotNullArgument(name, "name is null");
|
||||
Preconditions.checkNotNullArgument(name, "type is null");
|
||||
((KeyValueMetaClass) ds.metaClass).addProperty(new KeyValueMetaProperty(ds.metaClass, name, type));
|
||||
}
|
||||
|
||||
protected void loadData(Map<String, Object> params) {
|
||||
if (ds.needLoading()) {
|
||||
ValueLoadContext context = beforeLoadValues(params);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<KeyValueEntity> entities = ds.dataSupplier.loadValues(context);
|
||||
|
||||
afterLoadValues(params, context, entities);
|
||||
} catch (Throwable e) {
|
||||
ds.dataLoadError = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ValueLoadContext beforeLoadValues(Map<String, Object> params) {
|
||||
ValueLoadContext context = new ValueLoadContext();
|
||||
|
||||
ValueLoadContext.Query q = (ValueLoadContext.Query) ds.createDataQuery(context, params);
|
||||
if (q == null) {
|
||||
ds.detachListener(ds.data.values());
|
||||
ds.data.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ds.firstResult > 0)
|
||||
q.setFirstResult(ds.firstResult);
|
||||
|
||||
if (ds.maxResults > 0) {
|
||||
q.setMaxResults(ds.maxResults);
|
||||
}
|
||||
|
||||
if (storeName != null)
|
||||
context.setStoreName(storeName);
|
||||
|
||||
context.setSoftDeletion(ds.isSoftDeletion());
|
||||
|
||||
context.setIdName(idName);
|
||||
for (MetaProperty property : ds.metaClass.getProperties()) {
|
||||
context.addProperty(property.getName());
|
||||
}
|
||||
|
||||
ds.dataLoadError = null;
|
||||
return context;
|
||||
}
|
||||
|
||||
protected void afterLoadValues(Map<String, Object> params, ValueLoadContext context, List<KeyValueEntity> entities) {
|
||||
ds.detachListener(ds.data.values());
|
||||
ds.data.clear();
|
||||
|
||||
for (KeyValueEntity entity : entities) {
|
||||
ds.data.put(entity.getId(), entity);
|
||||
ds.attachListener(entity);
|
||||
entity.setMetaClass(ds.metaClass);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,23 +17,34 @@
|
||||
|
||||
package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaProperty;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.View;
|
||||
import com.haulmont.cuba.gui.data.DataSupplier;
|
||||
import com.haulmont.cuba.gui.data.DsContext;
|
||||
import com.haulmont.cuba.gui.data.GroupDatasource;
|
||||
import com.haulmont.cuba.gui.logging.UIPerformanceLogger;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.perf4j.StopWatch;
|
||||
import org.perf4j.log4j.Log4JStopWatch;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link GroupDatasource} that supports {@link KeyValueEntity}.
|
||||
*/
|
||||
public class KeyValueGroupDatasourceImpl extends GroupDatasourceImpl<KeyValueEntity, UUID> {
|
||||
public class ValueGroupDatasourceImpl
|
||||
extends GroupDatasourceImpl<KeyValueEntity, Object>
|
||||
implements ValueDatasource {
|
||||
|
||||
protected final ValueDatasourceDelegate delegate;
|
||||
|
||||
public ValueGroupDatasourceImpl() {
|
||||
delegate = new ValueDatasourceDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(DsContext dsContext, DataSupplier dataSupplier, String id, MetaClass metaClass, @Nullable View view) {
|
||||
@ -43,13 +54,35 @@ public class KeyValueGroupDatasourceImpl extends GroupDatasourceImpl<KeyValueEnt
|
||||
this.metaClass = new KeyValueMetaClass();
|
||||
}
|
||||
|
||||
public KeyValueGroupDatasourceImpl addProperty(String name) {
|
||||
((KeyValueMetaClass) metaClass).addProperty(new KeyValueMetaProperty(metaClass, name, String.class));
|
||||
@Override
|
||||
public ValueGroupDatasourceImpl setIdName(String name) {
|
||||
delegate.setIdName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueGroupDatasourceImpl addProperty(String name) {
|
||||
delegate.addProperty(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueGroupDatasourceImpl addProperty(String name, Class aClass) {
|
||||
delegate.addProperty(name, aClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueGroupDatasourceImpl addProperty(String name, Datatype type) {
|
||||
delegate.addProperty(name, type);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadData(Map<String, Object> params) {
|
||||
String tag = getLoggingTag("VGDS");
|
||||
StopWatch sw = new Log4JStopWatch(tag, Logger.getLogger(UIPerformanceLogger.class));
|
||||
|
||||
delegate.loadData(params);
|
||||
|
||||
sw.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,4 +96,8 @@ public class KeyValueGroupDatasourceImpl extends GroupDatasourceImpl<KeyValueEnt
|
||||
super.addItem(item);
|
||||
item.setMetaClass(metaClass);
|
||||
}
|
||||
|
||||
public void setStoreName(String storeName) {
|
||||
this.delegate.setStoreName(storeName);
|
||||
}
|
||||
}
|
@ -17,23 +17,34 @@
|
||||
|
||||
package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaClass;
|
||||
import com.haulmont.cuba.core.app.keyvalue.KeyValueMetaProperty;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.View;
|
||||
import com.haulmont.cuba.gui.data.DataSupplier;
|
||||
import com.haulmont.cuba.gui.data.DsContext;
|
||||
import com.haulmont.cuba.gui.data.HierarchicalDatasource;
|
||||
import com.haulmont.cuba.gui.logging.UIPerformanceLogger;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.perf4j.StopWatch;
|
||||
import org.perf4j.log4j.Log4JStopWatch;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* {@link HierarchicalDatasource} that supports {@link KeyValueEntity}.
|
||||
*/
|
||||
public class KeyValueHierarchicalDatasourceImpl extends HierarchicalDatasourceImpl<KeyValueEntity, UUID>{
|
||||
public class ValueHierarchicalDatasourceImpl
|
||||
extends HierarchicalDatasourceImpl<KeyValueEntity, Object>
|
||||
implements ValueDatasource {
|
||||
|
||||
protected final ValueDatasourceDelegate delegate;
|
||||
|
||||
public ValueHierarchicalDatasourceImpl() {
|
||||
delegate = new ValueDatasourceDelegate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup(DsContext dsContext, DataSupplier dataSupplier, String id, MetaClass metaClass, @Nullable View view) {
|
||||
@ -43,8 +54,24 @@ public class KeyValueHierarchicalDatasourceImpl extends HierarchicalDatasourceIm
|
||||
this.metaClass = new KeyValueMetaClass();
|
||||
}
|
||||
|
||||
public KeyValueHierarchicalDatasourceImpl addProperty(String name) {
|
||||
((KeyValueMetaClass) metaClass).addProperty(new KeyValueMetaProperty(metaClass, name, String.class));
|
||||
@Override
|
||||
public ValueHierarchicalDatasourceImpl setIdName(String name) {
|
||||
delegate.setIdName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueHierarchicalDatasourceImpl addProperty(String name) {
|
||||
delegate.addProperty(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueHierarchicalDatasourceImpl addProperty(String name, Class aClass) {
|
||||
delegate.addProperty(name, aClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueHierarchicalDatasourceImpl addProperty(String name, Datatype type) {
|
||||
delegate.addProperty(name, type);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -52,14 +79,19 @@ public class KeyValueHierarchicalDatasourceImpl extends HierarchicalDatasourceIm
|
||||
public void setHierarchyPropertyName(String hierarchyPropertyName) {
|
||||
super.setHierarchyPropertyName(hierarchyPropertyName);
|
||||
KeyValueMetaClass metaClass = (KeyValueMetaClass) this.metaClass;
|
||||
if (metaClass.getProperty(hierarchyPropertyName) != null) {
|
||||
metaClass.removeProperty(hierarchyPropertyName);
|
||||
if (metaClass.getProperty(hierarchyPropertyName) == null) {
|
||||
throw new IllegalStateException("Hierarchy property must be added to the datasource as property first");
|
||||
}
|
||||
metaClass.addProperty(new KeyValueMetaProperty(metaClass, hierarchyPropertyName, KeyValueEntity.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadData(Map<String, Object> params) {
|
||||
String tag = getLoggingTag("VHDS");
|
||||
StopWatch sw = new Log4JStopWatch(tag, Logger.getLogger(UIPerformanceLogger.class));
|
||||
|
||||
delegate.loadData(params);
|
||||
|
||||
sw.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,4 +105,8 @@ public class KeyValueHierarchicalDatasourceImpl extends HierarchicalDatasourceIm
|
||||
super.addItem(item);
|
||||
item.setMetaClass(metaClass);
|
||||
}
|
||||
|
||||
public void setStoreName(String storeName) {
|
||||
this.delegate.setStoreName(storeName);
|
||||
}
|
||||
}
|
@ -1926,6 +1926,76 @@
|
||||
<xs:attribute name="categorizedEntityClass" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- ValueCollectionDatasource -->
|
||||
<xs:complexType name="valueCollectionDatasourceType">
|
||||
<xs:sequence>
|
||||
<xs:element name="query" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="filter" type="filterType" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="properties" type="valueDatasourcePropertiesType"/>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="id" type="xs:string" use="required"/>
|
||||
<xs:attribute name="maxResults" type="xs:int"/>
|
||||
<xs:attribute name="store" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- ValueGroupDatasource -->
|
||||
<xs:complexType name="valueGroupDatasourceType">
|
||||
<xs:sequence>
|
||||
<xs:element name="query" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="filter" type="filterType" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="properties" type="valueDatasourcePropertiesType"/>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="id" type="xs:string" use="required"/>
|
||||
<xs:attribute name="maxResults" type="xs:int"/>
|
||||
<xs:attribute name="store" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- ValueHierarchicalDatasource -->
|
||||
<xs:complexType name="valueHierarchicalDatasourceType">
|
||||
<xs:sequence>
|
||||
<xs:element name="query" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:sequence>
|
||||
<xs:element name="filter" type="filterType" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="properties" type="valueDatasourcePropertiesType"/>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="id" type="xs:string" use="required"/>
|
||||
<xs:attribute name="maxResults" type="xs:int"/>
|
||||
<xs:attribute name="store" type="xs:string"/>
|
||||
<xs:attribute name="hierarchyProperty" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="valueDatasourcePropertiesType">
|
||||
<xs:sequence>
|
||||
<xs:element name="property" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:complexType mixed="true">
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="type" type="datatypeEnum" />
|
||||
<xs:attribute name="class" type="xs:string" />
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="properties" type="valueDatasourcePropertiesType"/>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="id" type="xs:string"/>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- PropertyDatasource -->
|
||||
<xs:group name="nestedDatasources">
|
||||
<xs:sequence>
|
||||
@ -2104,6 +2174,9 @@
|
||||
<xs:element name="collectionDatasource" type="collectionDatasourceType"/>
|
||||
<xs:element name="hierarchicalDatasource" type="hierarchicalDatasourceType"/>
|
||||
<xs:element name="runtimePropsDatasource" type="runtimePropsDatasourceType"/>
|
||||
<xs:element name="valueCollectionDatasource" type="valueCollectionDatasourceType"/>
|
||||
<xs:element name="valueGroupDatasource" type="valueGroupDatasourceType"/>
|
||||
<xs:element name="valueHierarchicalDatasource" type="valueHierarchicalDatasourceType"/>
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="class" type="xs:string"/>
|
||||
|
@ -17,15 +17,19 @@
|
||||
|
||||
package com.haulmont.cuba.gui.xml.data;
|
||||
|
||||
import com.haulmont.bali.util.Dom4j;
|
||||
import com.haulmont.bali.util.ReflectionHelper;
|
||||
import com.haulmont.chile.core.datatypes.Datatype;
|
||||
import com.haulmont.chile.core.datatypes.Datatypes;
|
||||
import com.haulmont.chile.core.datatypes.impl.StringDatatype;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.AppBeans;
|
||||
import com.haulmont.cuba.core.global.DevelopmentException;
|
||||
import com.haulmont.cuba.core.global.Metadata;
|
||||
import com.haulmont.cuba.core.global.Scripting;
|
||||
import com.haulmont.cuba.gui.data.*;
|
||||
import com.haulmont.cuba.gui.data.impl.DsContextImpl;
|
||||
import com.haulmont.cuba.gui.data.impl.DsContextImplementation;
|
||||
import com.haulmont.cuba.gui.data.impl.*;
|
||||
import com.haulmont.cuba.core.global.filter.QueryFilter;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dom4j.Element;
|
||||
@ -110,7 +114,25 @@ public class DsContextLoader {
|
||||
//noinspection unchecked
|
||||
elements = element.elements("runtimePropsDatasource");
|
||||
for (Element ds : elements) {
|
||||
loadRuntimePropsDataSource(ds);
|
||||
loadRuntimePropsDatasource(ds);
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
elements = element.elements("valueCollectionDatasource");
|
||||
for (Element ds : elements) {
|
||||
loadValueCollectionDatasource(ds);
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
elements = element.elements("valueGroupDatasource");
|
||||
for (Element ds : elements) {
|
||||
loadValueGroupDatasource(ds);
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
elements = element.elements("valueHierarchicalDatasource");
|
||||
for (Element ds : elements) {
|
||||
loadValueHierarchicalDatasource(ds);
|
||||
}
|
||||
|
||||
context.executeLazyTasks();
|
||||
@ -154,7 +176,7 @@ public class DsContextLoader {
|
||||
if (datasource instanceof CollectionDatasource.Suspendable)
|
||||
((CollectionDatasource.Suspendable) datasource).setSuspended(true);
|
||||
|
||||
loadQuery(element, metaClass, datasource);
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadDatasources(element, datasource);
|
||||
|
||||
@ -190,7 +212,7 @@ public class DsContextLoader {
|
||||
if (datasource instanceof CollectionDatasource.Suspendable)
|
||||
((CollectionDatasource.Suspendable) datasource).setSuspended(true);
|
||||
|
||||
loadQuery(element, metaClass, datasource);
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadDatasources(element, datasource);
|
||||
|
||||
@ -260,7 +282,7 @@ public class DsContextLoader {
|
||||
//noinspection unchecked
|
||||
elements = element.elements("runtimePropsDatasource");
|
||||
for (Element ds : elements) {
|
||||
loadRuntimePropsDataSource(ds);
|
||||
loadRuntimePropsDatasource(ds);
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,14 +379,14 @@ public class DsContextLoader {
|
||||
if (datasource instanceof CollectionDatasource.Suspendable)
|
||||
((CollectionDatasource.Suspendable) datasource).setSuspended(true);
|
||||
|
||||
loadQuery(element, metaClass, datasource);
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadDatasources(element, datasource);
|
||||
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private void loadQuery(Element element, MetaClass metaClass, CollectionDatasource datasource) {
|
||||
private void loadQuery(Element element, CollectionDatasource datasource) {
|
||||
Element queryElem = element.element("query");
|
||||
if (queryElem != null) {
|
||||
Element filterElem = queryElem.element("filter");
|
||||
@ -372,7 +394,7 @@ public class DsContextLoader {
|
||||
String query = queryElem.getText();
|
||||
if (!StringUtils.isBlank(query)) {
|
||||
if (filterElem != null)
|
||||
datasource.setQuery(query, new QueryFilter(filterElem, metaClass.getName()));
|
||||
datasource.setQuery(query, new QueryFilter(filterElem));
|
||||
else
|
||||
datasource.setQuery(query);
|
||||
}
|
||||
@ -414,7 +436,7 @@ public class DsContextLoader {
|
||||
return StringUtils.isEmpty(allowCommitStr) || Boolean.parseBoolean(allowCommitStr);
|
||||
}
|
||||
|
||||
protected RuntimePropsDatasource loadRuntimePropsDataSource(Element element){
|
||||
protected RuntimePropsDatasource loadRuntimePropsDatasource(Element element){
|
||||
String id = getDatasourceId(element);
|
||||
MetaClass metaClass = loadMetaClass(element);
|
||||
|
||||
@ -432,12 +454,103 @@ public class DsContextLoader {
|
||||
|
||||
builder.reset().setMetaClass(metaClass).setId(id);
|
||||
|
||||
RuntimePropsDatasource datasource = builder.buildRuntimePropsDataSource(mainDsId, categorizedEntityMetaClass);
|
||||
RuntimePropsDatasource datasource = builder.buildRuntimePropsDatasource(mainDsId, categorizedEntityMetaClass);
|
||||
|
||||
loadDatasources(element, datasource);
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private ValueCollectionDatasourceImpl loadValueCollectionDatasource(Element element) {
|
||||
String id = getDatasourceId(element);
|
||||
builder.reset().setMetaClass(metadata.getClassNN(KeyValueEntity.class)).setId(id);
|
||||
|
||||
ValueCollectionDatasourceImpl datasource = builder.buildValuesCollectionDatasource();
|
||||
|
||||
String maxResults = element.attributeValue("maxResults");
|
||||
if (!StringUtils.isEmpty(maxResults))
|
||||
datasource.setMaxResults(Integer.parseInt(maxResults));
|
||||
|
||||
datasource.setSuspended(true);
|
||||
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadProperties(element, datasource);
|
||||
|
||||
datasource.setStoreName(element.attributeValue("store"));
|
||||
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private ValueGroupDatasourceImpl loadValueGroupDatasource(Element element) {
|
||||
String id = getDatasourceId(element);
|
||||
builder.reset().setMetaClass(metadata.getClassNN(KeyValueEntity.class)).setId(id);
|
||||
|
||||
ValueGroupDatasourceImpl datasource = builder.buildValuesGroupDatasource();
|
||||
|
||||
String maxResults = element.attributeValue("maxResults");
|
||||
if (!StringUtils.isEmpty(maxResults))
|
||||
datasource.setMaxResults(Integer.parseInt(maxResults));
|
||||
|
||||
datasource.setSuspended(true);
|
||||
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadProperties(element, datasource);
|
||||
|
||||
datasource.setStoreName(element.attributeValue("store"));
|
||||
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private ValueHierarchicalDatasourceImpl loadValueHierarchicalDatasource(Element element) {
|
||||
String id = getDatasourceId(element);
|
||||
builder.reset().setMetaClass(metadata.getClassNN(KeyValueEntity.class)).setId(id);
|
||||
|
||||
ValueHierarchicalDatasourceImpl datasource = builder.buildValuesHierarchicalDatasourceImpl();
|
||||
|
||||
String maxResults = element.attributeValue("maxResults");
|
||||
if (!StringUtils.isEmpty(maxResults))
|
||||
datasource.setMaxResults(Integer.parseInt(maxResults));
|
||||
|
||||
datasource.setSuspended(true);
|
||||
|
||||
loadQuery(element, datasource);
|
||||
|
||||
loadProperties(element, datasource);
|
||||
|
||||
String hierarchyProperty = element.attributeValue("hierarchyProperty");
|
||||
if (!StringUtils.isEmpty(hierarchyProperty)) {
|
||||
datasource.setHierarchyPropertyName(hierarchyProperty);
|
||||
}
|
||||
|
||||
datasource.setStoreName(element.attributeValue("store"));
|
||||
|
||||
return datasource;
|
||||
}
|
||||
|
||||
private void loadProperties(Element element, ValueDatasource datasource) {
|
||||
Element propsEl = element.element("properties");
|
||||
if (propsEl != null) {
|
||||
for (Element propEl : Dom4j.elements(propsEl)) {
|
||||
String name = propEl.attributeValue("name");
|
||||
String className = propEl.attributeValue("class");
|
||||
if (className != null) {
|
||||
datasource.addProperty(name, ReflectionHelper.getClass(className));
|
||||
} else {
|
||||
String typeName = propEl.attributeValue("type");
|
||||
Datatype datatype = typeName == null ? Datatypes.get(StringDatatype.NAME) : Datatypes.get(typeName);
|
||||
datasource.addProperty(name, datatype);
|
||||
}
|
||||
}
|
||||
String idName = propsEl.attributeValue("id");
|
||||
if (idName != null) {
|
||||
if (datasource.getMetaClass().getProperty(idName) == null)
|
||||
throw new DevelopmentException(String.format("Property '%s' is not defined", idName));
|
||||
datasource.setIdName(idName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String getDatasourceId(Element element) {
|
||||
String id = element.attributeValue("id");
|
||||
for (Datasource datasource : context.getAll()) {
|
||||
|
@ -19,10 +19,8 @@ package com.haulmont.cuba.gui.data.impl;
|
||||
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.global.CommitContext;
|
||||
import com.haulmont.cuba.core.global.DataManager;
|
||||
import com.haulmont.cuba.core.global.LoadContext;
|
||||
import com.haulmont.cuba.core.global.View;
|
||||
import com.haulmont.cuba.core.entity.KeyValueEntity;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.gui.data.DataSupplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -116,6 +114,11 @@ public class TestDataSupplier implements DataSupplier {
|
||||
public void remove(Entity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KeyValueEntity> loadValues(ValueLoadContext context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataManager secure() {
|
||||
return this;
|
||||
|
@ -838,10 +838,8 @@ public abstract class WebAbstractTable<T extends com.vaadin.ui.Table & CubaEnhan
|
||||
Collection<MetaPropertyPath> paths = datasource.getView() != null ?
|
||||
// if a view is specified - use view properties
|
||||
metadataTools.getViewPropertyPaths(datasource.getView(), datasource.getMetaClass()) :
|
||||
// otherwise use only string properties from meta-class - the temporary solution for KeyValue datasources
|
||||
metadataTools.getPropertyPaths(datasource.getMetaClass()).stream()
|
||||
.filter(mpp -> mpp.getRangeJavaClass().equals(String.class))
|
||||
.collect(Collectors.toList());
|
||||
// otherwise use all properties from meta-class
|
||||
metadataTools.getPropertyPaths(datasource.getMetaClass());
|
||||
for (MetaPropertyPath metaPropertyPath : paths) {
|
||||
MetaProperty property = metaPropertyPath.getMetaProperty();
|
||||
if (!property.getRange().getCardinality().isMany() && !metadataTools.isSystem(property)) {
|
||||
|
Loading…
Reference in New Issue
Block a user