/**
* Copyright [2014] [Christian Loehnert]
*
* 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 de.ks.idnadrev.information.view;
import de.ks.datasource.ListDataSource;
import de.ks.idnadrev.entity.Category;
import de.ks.idnadrev.entity.Tag;
import de.ks.idnadrev.entity.information.ChartInfo;
import de.ks.idnadrev.entity.information.Information;
import de.ks.idnadrev.entity.information.TextInfo;
import de.ks.idnadrev.entity.information.UmlDiagramInfo;
import de.ks.persistence.PersistentWork;
import de.ks.persistence.entity.AbstractPersistentObject;
import de.ks.persistence.entity.NamedPersistentObject;
import de.ks.reflection.PropertyPath;
import org.apache.commons.lang3.StringUtils;
import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class InformationOverviewDS implements ListDataSource<InformationPreviewItem> {
private static final String KEY_NAME = PropertyPath.property(Information.class, NamedPersistentObject::getName);
private static final String KEY_CREATIONTIME = PropertyPath.property(Information.class, AbstractPersistentObject::getCreationTime);
private static final String KEY_TAGS = PropertyPath.property(Information.class, Information::getTags);
private static final String KEY_CATEGORY = PropertyPath.property(Information.class, Information::getCategory);
protected volatile InformationLoadingHint loadingHint = new InformationLoadingHint(null, "", null);
@Override
public List<InformationPreviewItem> loadModel(Consumer<List<InformationPreviewItem>> furtherProcessing) {
List<Class<? extends Information<?>>> classes = new ArrayList<>(Arrays.asList(TextInfo.class, ChartInfo.class, UmlDiagramInfo.class));
if (loadingHint.getType() != null) {
classes.clear();
classes.add(loadingHint.getType());
}
String name = "%" + StringUtils.replace(loadingHint.getName(), "*", "%") + "%";
List<String> tags = loadingHint.getTags();
Category category = loadingHint.getCategory();
List<InformationPreviewItem> retval = PersistentWork.read(em -> {
CriteriaBuilder builder = em.getCriteriaBuilder();
List<InformationPreviewItem> items = new ArrayList<>();
for (Class<? extends Information<?>> clazz : classes) {
List<InformationPreviewItem> results = getResults(name, tags, category, em, builder, clazz);
results.forEach(r -> r.setType(clazz));
items.addAll(results);
}
furtherProcessing.accept(items);
return items;
});
return retval;
}
private List<InformationPreviewItem> getResults(String name, List<String> tagNames, Category category, EntityManager em, CriteriaBuilder builder, Class<? extends Information<?>> clazz) {
CriteriaQuery<InformationPreviewItem> query = builder.createQuery(InformationPreviewItem.class);
Root<? extends Information<?>> root = query.from(clazz);
ArrayList<Predicate> filters = new ArrayList<>();
if (!name.isEmpty()) {
filters.add(builder.like(builder.lower(root.<String>get(KEY_NAME)), name));
}
if (!tagNames.isEmpty()) {
List<Tag> tags = getTags(tagNames, em);
SetJoin<TextInfo, Tag> tagJoin = root.joinSet(KEY_TAGS);
filters.add(tagJoin.in(tags));
}
if (category != null) {
filters.add(builder.equal(root.get(KEY_CATEGORY), category));
}
query.distinct(true);
query.where(filters.toArray(new Predicate[filters.size()]));
query.select(builder.construct(InformationPreviewItem.class, root.get(KEY_NAME), root.get(KEY_CREATIONTIME)));
List<InformationPreviewItem> resultList = em.createQuery(query).getResultList();
return resultList;
}
protected List<Tag> getTags(List<String> tagNames, EntityManager em) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Tag> query = builder.createQuery(Tag.class);
Root<Tag> root = query.from(Tag.class);
Path<String> namePath = root.get(KEY_NAME);
query.select(root);
query.where(namePath.in(tagNames));
return em.createQuery(query).getResultList();
}
@Override
public void setLoadingHint(Object dataSourceHint) {
if (dataSourceHint instanceof InformationLoadingHint) {
this.loadingHint = (InformationLoadingHint) dataSourceHint;
}
}
@Override
public void saveModel(List<InformationPreviewItem> model, Consumer<List<InformationPreviewItem>> beforeSaving) {
}
}