package crmdna.programtype;
import com.googlecode.objectify.Key;
import crmdna.client.Client;
import crmdna.common.MemcacheLock;
import crmdna.common.Utils;
import crmdna.common.api.APIException;
import crmdna.common.api.APIResponse.Status;
import crmdna.member.Member;
import crmdna.member.MemberLoader;
import crmdna.member.MemberQueryCondition;
import crmdna.practice.Practice;
import crmdna.practice.PracticeEntity;
import crmdna.sequence.Sequence;
import crmdna.sequence.Sequence.SequenceType;
import crmdna.user.User;
import crmdna.user.User.ClientLevelPrivilege;
import crmdna.user.User.ResourceType;
import crmdna.user.UserCore;
import java.util.*;
import java.util.Map.Entry;
import static crmdna.common.AssertUtils.ensure;
import static crmdna.common.AssertUtils.ensureNotNull;
import static crmdna.common.OfyService.ofy;
public class ProgramType {
public static ProgramTypeProp create(String client, String displayName, Set<Long> practiceIds,
String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_PROGRAM_TYPE);
ensureNotNull(displayName, "displayName is null");
ensure(displayName.length() != 0, "displayName is empty");
String name = Utils.removeSpaceUnderscoreBracketAndHyphen(displayName).toLowerCase();
List<Key<ProgramTypeEntity>> keys =
ofy(client).load().type(ProgramTypeEntity.class).filter("name", name).keys().list();
if (keys.size() != 0)
throw new APIException("There is already a program type with name [" + displayName + "]")
.status(Status.ERROR_RESOURCE_ALREADY_EXISTS);
try (MemcacheLock lock = new MemcacheLock(client, ResourceType.PROGRAM_TYPE, name)) {
ProgramTypeEntity entity = new ProgramTypeEntity();
entity.programTypeId = Sequence.getNext(client, SequenceType.PROGRAM_TYPE);
entity.name = name;
entity.displayName = displayName;
if (practiceIds != null) {
for (long practiceId : practiceIds) {
Practice.safeGet(client, practiceId);
entity.practiceIds.add(practiceId);
}
}
ofy(client).save().entity(entity).now();
return entity.toProp(client);
}
}
public static ProgramTypeProp updatePracticeIds(String client, long programTypeId,
Set<Long> newPracticeIds, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_PROGRAM_TYPE);
ensureNotNull(newPracticeIds, "newPracticeIds is null");
ProgramTypeEntity programTypeEntity = safeGet(client, programTypeId);
Set<Long> existingPracticeIds = programTypeEntity.practiceIds;
if (existingPracticeIds.containsAll(newPracticeIds)
&& newPracticeIds.containsAll(existingPracticeIds)) {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"newPracticeIds are identical to existing practice Ids");
}
Map<Long, PracticeEntity> map = Practice.getEntities(client, newPracticeIds);
if (map.size() != newPracticeIds.size())
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"One or more practiceIds not found");
programTypeEntity.practiceIds = map.keySet();
ofy(client).save().entity(programTypeEntity).now();
MemberQueryCondition mqc = new MemberQueryCondition(client, MemberLoader.MAX_RESULT_SIZE);
mqc.programTypeIds = Utils.getSet(programTypeId);
Member.rebuild(mqc, login);
return programTypeEntity.toProp(client);
}
public static ProgramTypeEntity safeGet(String client, long programTypeId) {
Client.ensureValid(client);
ProgramTypeEntity entity =
ofy(client).load().type(ProgramTypeEntity.class).id(programTypeId).now();
if (null == entity)
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Program type [" + programTypeId + "] does not exist");
return entity;
}
public static ProgramTypeEntity safeGetByIdOrName(String client, String idOrName) {
Client.ensureValid(client);
ensureNotNull(idOrName);
if (Utils.canParseAsLong(idOrName)) {
long programTypeId = Utils.safeParseAsLong(idOrName);
return safeGet(client, programTypeId);
}
idOrName = Utils.removeSpaceUnderscoreBracketAndHyphen(idOrName.toLowerCase());
List<ProgramTypeEntity> entities =
ofy(client).load().type(ProgramTypeEntity.class).filter("name", idOrName).list();
if (entities.size() == 0)
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Program Type [" + idOrName + "] does not exist");
if (entities.size() > 1)
// should never come here
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Found [" + entities.size() + "] matches for program type [" + idOrName
+ "]. Please specify Id");
return entities.get(0);
}
public static void ensureValid(String client, Set<Long> programTypeIds) {
Client.ensureValid(client);
Map<Long, ProgramTypeEntity> map =
ofy(client).load().type(ProgramTypeEntity.class).ids(programTypeIds);
if (map.size() == programTypeIds.size())
return; // all ids are valid
for (Long id : programTypeIds) {
if (!map.containsKey(id))
Utils.throwNotFoundException("programTypeId [" + id + "] does not exist");
}
}
public static List<ProgramTypeProp> getAll(String client) {
Client.ensureValid(client);
List<ProgramTypeEntity> entities =
ofy(client).load().type(ProgramTypeEntity.class).order("name").list();
List<ProgramTypeProp> props = new ArrayList<>();
for (ProgramTypeEntity entity : entities)
props.add(entity.toProp(client));
return props;
}
static Map<Long, ProgramTypeEntity> getEntities(String client, Set<Long> programTypeIds) {
Client.ensureValid(client);
ensureNotNull(programTypeIds, "programTypeIds is null");
Map<Long, ProgramTypeEntity> map =
ofy(client).load().type(ProgramTypeEntity.class).ids(programTypeIds);
return map;
}
public static Set<Long> getPracticeIds(String client, long programTypeId) {
Client.ensureValid(client);
return safeGet(client, programTypeId).practiceIds;
}
public static Set<Long> getPracticeIds(String client, Set<Long> programTypeIds) {
Client.ensureValid(client);
Map<Long, ProgramTypeEntity> map =
ofy(client).load().type(ProgramTypeEntity.class).ids(programTypeIds);
Set<Long> practiceIds = new HashSet<>();
for (Entry<Long, ProgramTypeEntity> entry : map.entrySet()) {
practiceIds.addAll(entry.getValue().practiceIds);
}
return practiceIds;
}
public static ProgramTypeProp rename(final String client, final long programTypeId,
final String newDisplayName, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_PROGRAM_TYPE);
ProgramTypeEntity entity = safeGet(client, programTypeId);
final String newName =
Utils.removeSpaceUnderscoreBracketAndHyphen(newDisplayName).toLowerCase();
// ensure unique if it not a simple upper case/lower case conversion
if (!entity.name.equals(newName)) {
List<Key<ProgramTypeEntity>> keys =
ofy(client).load().type(ProgramTypeEntity.class).filter("name", newName).keys().list();
if (keys.size() != 0)
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"There is already a program typee with name [" + newDisplayName + "]");
}
try (MemcacheLock lock = new MemcacheLock(client, ResourceType.PROGRAM_TYPE, newName)) {
entity.name = newName;
entity.displayName = newDisplayName;
ofy(client).save().entity(entity).now();
}
return entity.toProp(client);
}
public static void delete(String client, long programTypeId, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_PROGRAM_TYPE);
throw new APIException().status(Status.ERROR_NOT_IMPLEMENTED).message(
"Functionality to delete program type not yet implemented");
}
// this should be removed after bhairavi data migration is complete
public static void resaveAll(String client, String login) {
Client.ensureValid(client);
ensure(UserCore.isSuperUser(login), "Allowed only for super user");
List<ProgramTypeEntity> all = ofy(client).load().type(ProgramTypeEntity.class).list();
ofy(client).save().entities(all).now();
}
}