package pl.net.bluesoft.rnd.pt.ext.user.service;
import org.hibernate.FetchMode;
import org.hibernate.criterion.*;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.ReturningProcessToolContextCallback;
import pl.net.bluesoft.rnd.processtool.dao.UserDataDAO;
import pl.net.bluesoft.rnd.processtool.hibernate.CriteriaConfigurer;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry;
import pl.net.bluesoft.rnd.processtool.service.ProcessToolUserService;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class UserDataService implements ProcessToolUserService {
protected ProcessToolRegistry registry;
public UserDataService(ProcessToolRegistry registry) {
this.registry = registry;
}
protected <T> T withContext(ReturningProcessToolContextCallback<T> callback) {
return registry.withExistingOrNewContext(callback);
}
protected <T> T withContext(ProcessToolContext ctx, ReturningProcessToolContextCallback<T> callback) {
return ctx == null ? withContext(callback) : callback.processWithContext(ctx);
}
@Override
public UserData findUserByLogin(final String login) {
return withContext(new ReturningProcessToolContextCallback<UserData>() {
@Override
public UserData processWithContext(ProcessToolContext ctx) {
return ctx.getUserDataDAO().loadUserByLogin(login);
}
});
}
@Override
public UserData findUserByEmail(final String email) {
return withContext(new ReturningProcessToolContextCallback<UserData>() {
@Override
public UserData processWithContext(ProcessToolContext ctx) {
return ctx.getUserDataDAO().findUnique(Restrictions.eq("email", email));
}
});
}
@Override
public List<UserData> findUsersByExample(final UserData userData) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria().add(Example.create(userData)).addOrder(Order.asc("login"));
return ctx.getUserDataDAO().findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findAllUsers() {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
return ctx.getUserDataDAO().findAll();
}
});
}
@Override
public UserData findUserById(final Long id) {
return withContext(new ReturningProcessToolContextCallback<UserData>() {
@Override
public UserData processWithContext(ProcessToolContext ctx) {
return ctx.getUserDataDAO().findUnique(Restrictions.idEq(id));
}
});
}
@Override
public List<UserData> findUsersByLogins(final Collection<String> logins) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria().add(Restrictions.in("login", logins))
.addOrder(Order.asc("login"));
return dao.findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findUsersByEmails(final Collection<String> emails) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria().add(Restrictions.in("email", emails))
.addOrder(Order.asc("login"));
return dao.findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findUsersByIds(final Collection<Long> ids) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria().add(Restrictions.in("id", ids))
.addOrder(Order.asc("login"));
return dao.findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findUsersByAttribute(final String key, final String... values) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria()
.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)
.addOrder(Order.asc("login"))
.createCriteria("attributes")
.add(Restrictions.eq("key", key));
if(values.length == 1)
criteria.add(Restrictions.eq("value", values[0]));
else
criteria.add(Restrictions.in("value", values));
return dao.findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findUsersContainingAttributes(final String... key) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = dao.getDetachedCriteria()
.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)
.addOrder(Order.asc("login"))
.createCriteria("attributes")
.add(Restrictions.in("key", key));
return dao.findByCriteria(criteria);
}
});
}
@Override
public List<UserData> findUsersByAttributes(final Map<String, String> attributeValues) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria criteria = configureAttributesJoinCriteria(dao.getDetachedCriteria(), attributeValues);
return dao.findByCriteria(criteria);
}
});
}
protected DetachedCriteria configureAttributesJoinCriteria(DetachedCriteria root, Map<String, String> attributeValues) {
root.addOrder(Order.asc("login"));
root.setFetchMode("attributes", FetchMode.JOIN);
root.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
if (attributeValues != null && !attributeValues.isEmpty()) {
JoinAliasGenerator usr = new JoinAliasGenerator("usr"), ua = new JoinAliasGenerator("ua");
DetachedCriteria user = DetachedCriteria.forClass(UserData.class, usr.next());
for (Map.Entry<String, String> entry : attributeValues.entrySet()) {
String attributeAlias = ua.next();
user.createAlias(usr.last() + ".attributes", attributeAlias)
.add(Restrictions.eq(attributeAlias + ".key", entry.getKey()))
.add(Restrictions.eq(attributeAlias + ".value", entry.getValue()));
user.createAlias(attributeAlias + ".user", usr.next());
}
user.setResultTransformer(DetachedCriteria.PROJECTION);
user.setProjection(Projections.projectionList().add(Projections.id()));
root.add(Property.forName("id").in(user));
}
return root;
}
@Override
public List<UserData> findUsersByCriteria(final Criterion... criteria) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria detachedCriteria = dao.getDetachedCriteria();
for (Criterion c : criteria) {
detachedCriteria.add(c);
}
return dao.findByCriteria(detachedCriteria);
}
});
}
@Override
public List<UserData> findUsersByCriteria(Collection<Criterion> criteria) {
return findUsersByCriteria(criteria.toArray(new Criterion[criteria.size()]));
}
@Override
public List<UserData> findUsersByCriteria(final CriteriaConfigurer configurer) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
UserDataDAO dao = ctx.getUserDataDAO();
DetachedCriteria detachedCriteria = dao.getDetachedCriteria();
configurer.configure(detachedCriteria);
return dao.findByCriteria(detachedCriteria);
}
});
}
@Override
public UserData updateUser(final UserData user) {
return withContext(new ReturningProcessToolContextCallback<UserData>() {
@Override
public UserData processWithContext(ProcessToolContext ctx) {
return updateUserInternal(ctx, user);
}
});
}
protected UserData updateUserInternal(ProcessToolContext ctx, UserData user) {
UserDataDAO dao = ctx.getUserDataDAO();
UserData base = dao.loadOrCreateUserByLogin(user);
UserData merged = UserConverterUtils.mergeUsers(base, user);
dao.saveOrUpdate(merged);
return merged;
}
@Override
public List<UserData> updateUsers(final Collection<UserData> users) {
return withContext(new ReturningProcessToolContextCallback<List<UserData>>() {
@Override
public List<UserData> processWithContext(ProcessToolContext ctx) {
return updateUsersInternal(ctx, users);
}
});
}
protected List<UserData> updateUsersInternal(ProcessToolContext ctx, Collection<UserData> users) {
List<UserData> mergedUsers = new LinkedList<UserData>();
for (UserData user : users) {
mergedUsers.add(updateUserInternal(ctx, user));
}
return mergedUsers;
}
}