package qa.qcri.aidr.dbmanager.ejb.remote.facade.imp; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.ejb.Asynchronous; import javax.ejb.EJB; import javax.ejb.Stateless; import org.apache.commons.lang3.text.translate.UnicodeEscaper; import org.apache.log4j.Logger; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Restrictions; import qa.qcri.aidr.common.exception.PropertyNotSetException; import qa.qcri.aidr.dbmanager.dto.CollectionDTO; import qa.qcri.aidr.dbmanager.dto.DocumentDTO; import qa.qcri.aidr.dbmanager.dto.DocumentNominalLabelDTO; import qa.qcri.aidr.dbmanager.dto.DocumentNominalLabelIdDTO; import qa.qcri.aidr.dbmanager.dto.HumanLabeledDocumentDTO; import qa.qcri.aidr.dbmanager.dto.ModelFamilyDTO; import qa.qcri.aidr.dbmanager.dto.NominalAttributeDTO; import qa.qcri.aidr.dbmanager.dto.NominalLabelDTO; import qa.qcri.aidr.dbmanager.dto.TaskAnswerDTO; import qa.qcri.aidr.dbmanager.dto.TaskAssignmentDTO; import qa.qcri.aidr.dbmanager.dto.UsersDTO; import qa.qcri.aidr.dbmanager.ejb.remote.facade.ModelFamilyResourceFacade; import qa.qcri.aidr.dbmanager.ejb.remote.facade.TaskManagerRemote; import qa.qcri.aidr.dbmanager.entities.misc.Collection; import qa.qcri.aidr.dbmanager.entities.misc.Users; import qa.qcri.aidr.dbmanager.entities.task.Document; import qa.qcri.aidr.dbmanager.entities.task.DocumentNominalLabel; import qa.qcri.aidr.dbmanager.entities.task.TaskAnswer; import qa.qcri.aidr.dbmanager.entities.task.TaskAssignment; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; /** * This class implements the TaskManagerRemote interface, providing the business logic for operations * on the document, document_nominal_label, task_answer and task_assignment table - logically grouped as the the 'task related operations'. * * @author Koushik * */ @Stateless public class TaskManagerBean<T, I> implements TaskManagerRemote<T, Serializable> { @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.CollectionResourceFacade remoteCrisisEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.DocumentResourceFacade remoteDocumentEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.UsersResourceFacade remoteUsersEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.DocumentNominalLabelResourceFacade remoteDocumentNominalLabelEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.CrisisTypeResourceFacade remoteCrisisTypeEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.TaskAnswerResourceFacade remoteTaskAnswerEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.TaskAssignmentResourceFacade remoteTaskAssignmentEJB; @EJB private qa.qcri.aidr.dbmanager.ejb.remote.facade.NominalLabelResourceFacade remoteNominalLabelEJB; @EJB private ModelFamilyResourceFacade modelFamilyResourceFacade; protected static Logger logger = Logger.getLogger(TaskManagerBean.class); private static UnicodeEscaper unicodeEscaper = UnicodeEscaper.above(127); private static Object lockObject = new Object(); private static Integer inCS = 0; private Class<T> entityType; public TaskManagerBean() { this.entityType = getClassType(); //lock = new ReentrantLock(); } //private static final Object monitor = new Object(); @SuppressWarnings("unchecked") public Class<T> getClassType() { Class<? extends Object> thisClass = getClass(); Type genericSuperclass = thisClass.getGenericSuperclass(); if( genericSuperclass instanceof ParameterizedType ) { Type[] argumentTypes = ((ParameterizedType) genericSuperclass).getActualTypeArguments(); Class<T> entityBeanType = (Class<T>)argumentTypes[0]; return entityBeanType; } else { return null; } } @Override public long insertNewTask(T task) { if (task == null) { logger.warn("Attempting to insert null task"); return -1; } DocumentDTO doc = (DocumentDTO) task; doc.setHasHumanLabels(false); try { //documentLocalEJB.save(doc); DocumentDTO savedDoc = remoteDocumentEJB.addDocument(doc); return savedDoc.getDocumentID(); } catch (Exception e) { logger.error("Error in document insertion : " + doc.getData()); } return -1; } @Override public Long saveNewTask(T task, Long crisisID) { if (task == null) { logger.error("Attempting to insert empty task"); return -1L; } try { DocumentDTO doc = (DocumentDTO) task; CollectionDTO crisisDTO = remoteCrisisEJB.findCrisisByID(crisisID); doc.setCrisisDTO(crisisDTO); doc.setHasHumanLabels(false); DocumentDTO savedDoc = remoteDocumentEJB.addDocument(doc); //logger.info("Saved to DB document: " + savedDoc.getDocumentID() + ", for crisis = " + savedDoc.getCrisisDTO().getCode()); if(savedDoc != null) { return savedDoc.getDocumentID(); } } catch (Exception e) { logger.error("Error in saving new document for crisisID : " + crisisID , e); } return -1L; } @Override public void insertNewTask(List<T> collection) { if (collection != null) { try { for (T doc: collection) { ((DocumentDTO) doc).setHasHumanLabels(false); remoteDocumentEJB.addDocument((DocumentDTO) doc); } } catch (Exception e) { logger.error("Error in collection insertion"); } } else { logger.warn("Attempting to insert NULL"); } } @Override public List<Long> saveNewTasks(List<T> collection, Long crisisID) { List<Long> newList = new ArrayList<Long>(); if (collection != null) { try { for (T doc: collection) { CollectionDTO crisisDTO = remoteCrisisEJB.findCrisisByID(crisisID); ((DocumentDTO) doc).setCrisisDTO(crisisDTO); ((DocumentDTO) doc).setHasHumanLabels(false); DocumentDTO savedDoc = remoteDocumentEJB.addDocument((DocumentDTO) doc); if (savedDoc != null) { newList.add(savedDoc.getDocumentID()); } } } catch (Exception e) { logger.error("Error in collection insertion for crisisID : " + crisisID); } } else { logger.warn("Attempting to insert NULL"); } return newList; } @Override public int deleteTaskById(Long id) { try { DocumentDTO doc = remoteDocumentEJB.findDocumentByID(id); Integer result = remoteDocumentEJB.deleteNoLabelDocument(doc); return result; } catch(Exception e) { logger.error("Error in deletion by id"); } return 0; } @Override public int deleteTask(T task) { if (task != null) { try { return remoteDocumentEJB.deleteNoLabelDocument((DocumentDTO) task); } catch (Exception e) { logger.error("Error in deletion of task"); return 0; } } else { logger.warn("Attempting to delete NULL"); } return 0; } private List<DocumentDTO> createDocumentDTOList(List<Document> list) throws PropertyNotSetException { List<DocumentDTO> dtoList = new ArrayList<DocumentDTO>(); if (list != null) { for (Document d : list) { dtoList.add(new DocumentDTO(d)); } } return dtoList; } private List<Document> createDocumentEntityList(List<DocumentDTO> list) throws PropertyNotSetException { List<Document> eList = new ArrayList<Document>(); if (list != null) { for (DocumentDTO d : list) { eList.add(d.toEntity()); } } return eList; } @SuppressWarnings("unchecked") @Override public int deleteTask(List<T> collection) { List<DocumentDTO> dtoList = null; if (collection != null) { try { dtoList = createDocumentDTOList((List<Document>) collection); } catch (PropertyNotSetException e) { logger.error("Unable to create DTO list.", e); } try { return remoteDocumentEJB.deleteNoLabelDocument(dtoList); } catch (Exception e) { logger.error("Error in collection deletion of size: " + collection.size()); return 0; } } else { logger.warn("Attempting to delete a NULL collection"); } return 0; } @Override public int deleteUnassignedTask(T task) { if (task != null) { try { return remoteDocumentEJB.deleteUnassignedDocument((DocumentDTO) task); } catch (Exception e) { logger.error("Error in deletion"); return 0; } } else { logger.warn("Attempting to delete NULL"); } return 0; } @SuppressWarnings("unchecked") @Override public int deleteUnassignedTaskCollection(List<T> collection) { if (collection != null) { List<Long> idList = new ArrayList<Long>(); for (DocumentDTO dto: (List<DocumentDTO>) collection) { idList.add(dto.getDocumentID()); } try { return remoteDocumentEJB.deleteUnassignedDocumentCollection(idList); } catch (Exception e) { logger.error("Error in collection deletion"); return 0; } } else { logger.warn("Attempting to delete NULL collection"); } return 0; } @Override public int deleteStaleTasks(String joinType, String joinTable, String joinColumn, String sortOrder, String[] orderBy, final String maxTaskAge, final String scanInterval) { //logger.info("Received request: " + joinType + ", " + joinTable + ", " // + joinColumn + ", " + maxTaskAge + ", " + scanInterval); try { int docDeleteCount = remoteDocumentEJB.deleteStaleDocuments(joinType, joinTable, joinColumn, sortOrder, orderBy, maxTaskAge, scanInterval); return docDeleteCount; } catch (Exception e) { logger.warn("Error in deletion"); return 0; } } @Override public int truncateLabelingTaskBufferForCrisis(final long crisisID, final int maxLength, final int ERROR_MARGIN) { List<Long> docList = null; try { docList = remoteDocumentEJB.getUnassignedDocumentIDsByCrisisID(crisisID, null); } catch (Exception e) { logger.error("Exception in fetching unassigned documents with hasHumaLabels=false"); return 0; } DocumentDTO dto; // Next trim the document table for the given crisisID to the // Config.LABELING_TASK_BUFFER_MAX_LENGTH size if (docList != null) { int docsToDelete = docList.size() - maxLength; if (docsToDelete > ERROR_MARGIN) { // if less than this, then skip delete //List<Long> documentIDList = new ArrayList<Long>(); for (int i = 0;i < docsToDelete;i++) { try { dto = remoteDocumentEJB.findDocumentByID(docList.get(i)); remoteDocumentEJB.deleteDocument(dto); } catch (Exception e) { logger.error("Exception when attempting to delete document"); } } return docsToDelete; } else { logger.debug("No need for truncation: docListSize = " + docList.size() + ", max buffer size = " + maxLength); } } return 0; } @Override public void updateTask(T task) { try { // NOTE: can't use update() since serialization+deserialization // of persisted entity will throw an exception. Use merge() instead. //documentLocalEJB.update((Document) task); remoteDocumentEJB.merge(((DocumentDTO) task).toEntity()); } catch (Exception e) { logger.error("failed update"); } } @SuppressWarnings("unchecked") @Override public void updateTaskList(List<T> collection) { try { // NOTE: can't use update() since serialization+deserialization // of persisted entity will throw an exception. Use merge() instead. //documentLocalEJB.update((List<Document>) collection); remoteDocumentEJB.merge(createDocumentEntityList((List<DocumentDTO>)collection)); } catch (Exception e) { logger.error("failed collection update"); } } @Override public void updateTask(DocumentDTO dto) { try { // NOTE: can't use update() since serialization+deserialization // of persisted entity will throw an exception. Use merge() instead. //documentLocalEJB.update((Document) task); remoteDocumentEJB.merge(dto.toEntity()); } catch (Exception e) { logger.error("failed update"); } } /** * Gets a new task from the task repository * @param <entityClass> */ @Override public DocumentDTO getNewTask(Long crisisID) { try { return getNewTask(crisisID, null); } catch (Exception e) { logger.error("Error in fetching new task.", e); } return null; } /** * Gets a new task from the task repository * based on specified criterion */ @Override public DocumentDTO getNewTask(Long crisisID, Criterion criterion) { Criterion newCriterion = null; try { if (criterion != null) { newCriterion = Restrictions.conjunction() .add(criterion) .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels",false)); } else { newCriterion = Restrictions.conjunction() .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels",false)); } Document document = remoteDocumentEJB.getByCriteria(newCriterion); //logger.debug("New task: " + document); if (document != null && !isTaskAssigned(document)) { logger.info("New task: " + document.getDocumentId()); return new DocumentDTO(document); } } catch (Exception e) { logger.error("Error in getting new Task for crisisID: " + crisisID); } return null; } @Override public List<DocumentDTO> getNewTaskCollection(Long crisisID, Integer count, String order, Criterion criterion) { logger.debug("Received request for crisisID = " + crisisID + ", count = " + count); String aliasTable = "taskAssignments"; String aliasTableKey = "taskAssignments.id.documentId"; String[] orderBy = {"valueAsTrainingSample","documentId"}; Criterion newCriterion = criterion; if (criterion != null) { newCriterion = Restrictions.conjunction() .add(criterion) .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels",false)); } else { newCriterion = Restrictions.conjunction() .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels",false)); } Criterion aliasCriterion = (Restrictions.isNull(aliasTableKey)); try { List<Document> docList = remoteDocumentEJB.getByCriteriaWithAliasByOrder(newCriterion, order, orderBy, count, aliasTable, aliasCriterion); if (docList != null) { logger.debug("[getNewTaskCollection] Fetched size = " + docList.size()); return createDocumentDTOList(docList); } else { return null; } } catch (Exception e) { logger.error("Error in getting new Task collection for crisisID: " + crisisID); } return null; } @Override public <E> Boolean isTaskAssigned(E task) { List<TaskAssignmentDTO> fetchedList = null; if (task != null) { try { DocumentDTO document = (DocumentDTO) task; fetchedList= remoteTaskAssignmentEJB.findTaskAssignmentByID(document.getDocumentID()); } catch (Exception e) { logger.error("Error in finding Task"); return false; } } if (null == fetchedList || fetchedList.isEmpty()) { return false; } return true; } @Override public <E> Boolean isTaskNew(E task) { if (task != null && !isTaskAssigned(task) && !isTaskDone(task)) { return true; } else { return false; } } @Override public <E> Boolean isTaskDone(E task) { if (task != null) { try { Document document = remoteDocumentEJB.getById(((DocumentDTO) task).getDocumentID()); if ((document != null) && ((Document) document).isHasHumanLabels()) { return true; } } catch (Exception e) { logger.error("Error in finding document"); return false; } } return false; // no entry for documentID in task_answer table } @Override public <E> Boolean isExists(E task) { if (task != null) { DocumentDTO document = (DocumentDTO) task; try { if (remoteDocumentEJB.getById(document.getDocumentID()) != null) { return true; } } catch (Exception e) { logger.error("Error in finding document"); } } return false; } @Override public DocumentDTO getTaskByCriterion(Long crisisID, Criterion criterion) { try { if (criterion != null) { Criterion newCriterion = Restrictions.conjunction() .add(criterion) .add(Restrictions.eq("collection.id", crisisID)); Document document = remoteDocumentEJB.getByCriteria(newCriterion); return new DocumentDTO(document); } } catch (Exception e) { logger.error("Error in finding task"); } return null; } @Override public List<DocumentDTO> getTaskCollectionByCriterion(Long crisisID, Integer count, Criterion criterion) { try { if (criterion != null) { Criterion newCriterion = Restrictions.conjunction() .add(criterion) .add(Restrictions.eq("collection.id", crisisID)); List<Document> docList = remoteDocumentEJB.getByCriteriaWithLimit(newCriterion, count); return createDocumentDTOList(docList); } } catch (Exception e) { logger.error("Error in finding task"); } return null; } @Override public List<DocumentDTO> getNominalLabelDocumentCollection(Long nominalLabelID) { logger.info("Received fetch document request with nominal label = " + nominalLabelID); try { List<DocumentDTO> docList = remoteDocumentEJB.getDocumentCollectionWithNominalLabelData(nominalLabelID); logger.debug("docList = " + docList); if (docList != null) { //logger.info("Fetched size = " + docList.size()); return docList; } } catch (Exception e) { logger.error("Error in getting new document collection for nominal Label ID: " + nominalLabelID); } return null; } @Override public void taskUpdate(Criterion criterion, String joinType, String joinTable, String joinColumn, String sortOrder, String[] orderBy) { // TODO Auto-generated method stub } @Override public DocumentDTO getTaskById(Long id) { try { DocumentDTO document = remoteDocumentEJB.findDocumentByID(id); logger.debug("Fetched document: " + document); return document; } catch (Exception e) { logger.error("Error in finding task"); } return null; } @Override public List<DocumentDTO> getAllTasks() { try { List<Document> docList = remoteDocumentEJB.getAll(); logger.debug("Fetched documents count: " + docList.size()); return createDocumentDTOList(docList); } catch (Exception e) { logger.error("Error in finding task"); } return null; } @Override public <E> String serializeTask(E task) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); String jsonString = null; try { if (task != null) jsonString = mapper.writeValueAsString(task); } catch (IOException e) { logger.error("JSON serialization exception"); } return jsonString; } /** * Example method call: deSerializeList(jsonString2, new TypeReference<List<Document>>() {}) */ @Override public <E> E deSerializeList(String jsonString, TypeReference<E> type) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { if (jsonString != null) { E docList = mapper.readValue(jsonString, type); return docList; } } catch (IOException e) { logger.error("JSON deserialization exception"); } return null; } /** * Example method call: deSerialize(jsonString, Document.class) */ @Override public <E> E deSerialize(String jsonString, Class<E> entityType) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { if (jsonString != null) { E entity = mapper.readValue(jsonString, entityType); return entity; } } catch (IOException e) { logger.error("JSON deserialization exception"); } return null; } //////////////////////////////////////////////////////////// // Trainer API Task Assignment related APIs //////////////////////////////////////////////////////////// @Override public List<DocumentDTO> getDocumentsForTagging(final Long crisisID, int count, final String userName, final int remainingCount) { UsersDTO users = null; List<DocumentDTO> assignList = null; try { users = remoteUsersEJB.getUserByName(userName); } catch (Exception e) { logger.error("[getDocumentsForTagging] Exception in finding user userName = " + userName + ". Aborting..."); logger.error("Exception", e); } if (users != null) { int fetchedSize = 0; try { List<DocumentDTO> dtoList = getNewTaskCollection(crisisID, count, "DESC", null); if (dtoList != null) { fetchedSize = dtoList.size(); } int availableRequestSize = fetchedSize - remainingCount; if (availableRequestSize > 0) { count = Math.min(count, availableRequestSize); if (!dtoList.isEmpty() && count > 0) { assignList = new ArrayList<DocumentDTO>(); assignList.addAll(dtoList.subList(0, count)); assignNewTaskToUser(assignList, users.getUserID()); } } } catch (Exception e) { logger.error("Exception", e); } } else { logger.warn("[getDocumentsForTagging] No user found with userName = " + userName + ". Aborting..."); } return assignList; } @Override public void assignNewTaskToUser(Long id, Long userId) throws Exception { try { int retVal = remoteTaskAssignmentEJB.insertOneTaskAssignment(id, userId); if (retVal <= 0) { logger.error("unable to assign new task to user"); throw new Exception("[assignNewTaskToUser] Couldn't do task assignment"); } } catch (Exception e) { logger.error("Error in assignNewTaskToUser for id : " + id + " and userID : " + userId); } } @Override @SuppressWarnings("unchecked") public void assignNewTaskToUser(List<DocumentDTO> collection, Long userId) throws Exception { int retVal = remoteTaskAssignmentEJB.insertTaskAssignment(collection, userId); if (retVal <= 0) { logger.warn("Unable to insert task assignment"); throw new Exception("[assignNewTaskToUser] Couldn't do task assignment"); } } @Override public void undoTaskAssignment(Map<Long, Long> taskMap) throws Exception { int retVal = remoteTaskAssignmentEJB.undoTaskAssignment(taskMap); if (retVal <= 0) { logger.warn("Unable to undo task assignment"); throw new Exception("[undoTaskAssignment] Couldn't undo task assignment"); } } @Override public void undoTaskAssignment(Long id, Long userId) throws Exception { int retVal = remoteTaskAssignmentEJB.undoTaskAssignment(id, userId); if (retVal <= 0) { logger.warn("Unable to undo task assignment"); throw new Exception("[undoTaskAssignment] Couldn't undo task assignment"); } } @Override public Integer getPendingTaskCountByUser(Long userId) { return remoteTaskAssignmentEJB.getPendingTaskCount(userId); } @Override public List<TaskAssignmentDTO> getAssignedTasksById(Long id) { List<TaskAssignmentDTO> docList = remoteTaskAssignmentEJB.findTaskAssignmentByID(id); if (docList != null) { try { return docList; } catch (Exception e) { logger.error("Error in serializing collection"); } } return null; } @Override public TaskAssignmentDTO getAssignedTaskByUserId(Long id, Long userId) { TaskAssignmentDTO assignedUserTask = remoteTaskAssignmentEJB.findTaskAssignment(id, userId); if (assignedUserTask != null) { try { return assignedUserTask; } catch (Exception e) { logger.error("Error in serializing collection"); } } return null; } /** * Takes as input a map consisting of the setter methods and their corresponding parameters * of the entity to be modified. Returns the modified entity. */ @Override public <E> Object setTaskParameter(Class<E> entityType, Long id, Map<String, String> paramMap) { //logger.info("Received request for task ID = " + id + ", param Map = " + paramMap); Object doc = null; try { if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.Document.class)) { //logger.info("Detected of type Document.class, id = " + id); doc = (Document) remoteDocumentEJB.getById(id); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.TaskAssignment.class)) { //logger.info("Detected of type TaskAssignment.class"); doc = (TaskAssignment) remoteTaskAssignmentEJB.getById(id); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.TaskAnswer.class)) { //logger.info("Detected of type TaskAnswer.class"); List<TaskAnswerDTO> docList = remoteTaskAnswerEJB.getTaskAnswer(id); if (docList != null) doc = docList.get(0).toEntity(); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.misc.Users.class)) { //logger.info("Detected of type Users.class"); doc = (Users) remoteUsersEJB.getById(id); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.DocumentNominalLabel.class)) { //logger.info("Detected of type DocumentNominalLabel.class"); doc = (DocumentNominalLabel) remoteDocumentNominalLabelEJB.getById(id); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.misc.Collection.class)) { doc = (Collection) remoteCrisisEJB.getById(id); } //logger.info("Fetched task of type: " + doc.getClass()); //logger.info("received map: " + paramMap); } catch (Exception e) { logger.error("Error in detecting Class Type"); return null; } if (doc != null) { Class docClass = null; //Object obj = null; Method[] methods = null; Class[] paramTypes = null; try { //docClass = Class.forName(className); docClass = entityType; //obj = docClass.newInstance(); methods = docClass.getDeclaredMethods(); for (int i = 0; i < methods.length;i++) { //logger.info("discovered method: " + methods[i].getName()); } } catch (Exception e) { logger.error("Error in instantiating method class"); return null; } Iterator<String> itr = paramMap.keySet().iterator(); while (itr.hasNext()) { String name = itr.next(); try { int pointer = -1; for (int j = 0;j < methods.length;j++) { if (methods[j].getName().equals(name)) { pointer = j; break; } } paramTypes = methods[pointer].getParameterTypes(); for (int j = 0; j < paramTypes.length;j++) { //logger.info(methods[pointer].getName() + ": discovered parameter types: " + paramTypes[j].getName()); } // Convert parameter to paramType if (paramTypes[0].getName().toLowerCase().contains("long")) { methods[pointer].invoke(doc, Long.parseLong(paramMap.get(name))); //logger.info("Invoking with Long parameter type"); } if (paramTypes[0].getName().toLowerCase().contains("int")) { methods[pointer].invoke(doc, Integer.parseInt(paramMap.get(name))); //logger.info("Invoking with Integer parameter type"); } if (paramTypes[0].getName().toLowerCase().equals("boolean")) { methods[pointer].invoke(doc, Boolean.parseBoolean(paramMap.get(name))); //logger.info("Invoking with Boolean parameter type"); } if (paramTypes[0].getName().equals("String")) { methods[pointer].invoke(doc, paramMap.get(name)); } } catch (Exception e) { logger.error("Error in invoking method via reflection: "); return null; } } } try { logger.info("Will attempt to merge update with document ID = " + id); if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.Document.class)) { //logger.info("Detected of type Document.class, id = " + id); remoteDocumentEJB.merge((Document) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.Document) doc); return new DocumentDTO((Document) doc); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.TaskAssignment.class)) { //logger.info("Detected of type TaskAssignment.class"); remoteTaskAssignmentEJB.merge((TaskAssignment) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.TaskAssignment) doc); return new TaskAssignmentDTO((TaskAssignment) doc); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.TaskAnswer.class)) { //logger.info("Detected of type TaskAnswer.class"); remoteTaskAnswerEJB.merge((TaskAnswer) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.TaskAnswer) doc); return new TaskAnswerDTO((TaskAnswer) doc); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.misc.Users.class)) { //logger.info("Detected of type Users.class"); remoteUsersEJB.merge((Users) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.Users) doc); return new UsersDTO((Users) doc); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.task.DocumentNominalLabel.class)) { //logger.info("Detected of type DocumentNominalLabel.class"); remoteDocumentNominalLabelEJB.merge((DocumentNominalLabel) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.DocumentNominalLabel) doc); return new DocumentNominalLabelDTO((DocumentNominalLabel) doc); } if (entityType.equals(qa.qcri.aidr.dbmanager.entities.misc.Collection.class)) { remoteCrisisEJB.merge((Collection) doc); logger.debug("Merge update successful for task id = " + id); //return serializeTask((qa.qcri.aidr.task.entities.Crisis) doc); return new CollectionDTO((Collection) doc); } } catch (Exception e) { logger.error("Error in updating entity on DB"); } return null; } @Override public void insertTaskAnswer(TaskAnswerDTO taskAnswer) { try { remoteTaskAnswerEJB.insertTaskAnswer(taskAnswer); } catch (Exception e) { logger.error("Error in saving task answer : " + taskAnswer.getDocumentID() + ", " + taskAnswer.getAnswer() + ", " + taskAnswer.getUserID()); } } //////////////////////////////////////////// // User service related APIs //////////////////////////////////////////// @Override public UsersDTO getUserByName(String name) { UsersDTO user = null; try { user = remoteUsersEJB.getUserByName(name); } catch (PropertyNotSetException e) { logger.error("Error in getUserByName for name : " + name, e); } return user; } @Override public UsersDTO getUserById(Long id) { UsersDTO user = null; try { user = remoteUsersEJB.getUserById(id); } catch (PropertyNotSetException e) { logger.error("Error in getUserById for id : " + id, e); } //return serializeTask(user); return user; } @Override public List<UsersDTO> getAllUserByName(String name) { List<UsersDTO> userList = new ArrayList<UsersDTO>(); try { userList = remoteUsersEJB.getAllUsersByName(name); } catch (PropertyNotSetException e) { logger.error("Error in getAllUserByName for name : " + name, e); } return userList; } ////////////////////////??//////////////////// // DocumentNominalLabel service related APIs //////////////////////////??////////////////// @Override public void saveDocumentNominalLabel(DocumentNominalLabelDTO documentNominalLabel) { try { DocumentNominalLabelDTO dto = remoteDocumentNominalLabelEJB.addDocument(documentNominalLabel); logger.info("Saved to DB document nominal label: " + dto.getIdDTO().getDocumentId() + ", with nominal label = " + dto.getIdDTO().getNominalLabelId()); } catch (Exception e) { logger.error("Error in saving document nominal label : " + documentNominalLabel, e); } } @Override public boolean foundDuplicateDocumentNominalLabel(DocumentNominalLabelDTO documentNominalLabel) { Map<String, Long> attMap = new HashMap<String, Long>(); try { attMap.put("id.documentId", documentNominalLabel.getIdDTO().getDocumentId()); attMap.put("id.nominalLabelId", documentNominalLabel.getIdDTO().getNominalLabelId()); } catch (PropertyNotSetException e) { logger.warn("Warning! duplication nominal label"); } DocumentNominalLabel obj = remoteDocumentNominalLabelEJB.getByCriterionID(Restrictions.allEq(attMap)); if(obj != null) { return true; } else { return false; //To change body of implemented methods use File | Settings | File Templates. } } @Override public DocumentDTO getDocumentById(Long id) { try { Document document = remoteDocumentEJB.getById(id); logger.debug("Fetched document: " + document); return new DocumentDTO(document); } catch (Exception e) { logger.error("Error in finding task"); } return null; } @Override public String pingRemoteEJB() { StringBuilder sb = new StringBuilder("{\"status\": \"RUNNING\"}"); return sb.toString(); } @Override public List<HumanLabeledDocumentDTO> getHumanLabeledDocumentsByCrisisID(Long crisisID, Integer count) throws Exception { if (null == crisisID) { logger.error("crisisID can't be null"); throw new PropertyNotSetException("crisisID can't be null"); } logger.debug("Received request for crisisID = " + crisisID + ", count = " + count); List <HumanLabeledDocumentDTO> labeledDocList = null; String aliasTable = "documentNominalLabels"; String aliasTableKeyField = "documentNominalLabels.id.nominalLabelId"; String[] orderBy = {"documentId"}; Criterion criterion = Restrictions.conjunction() .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels", true)); Criterion aliasCriterion = Restrictions.isNotNull(aliasTableKeyField); try { List<Document> docList = remoteDocumentEJB.getByCriteriaWithInnerJoinByOrder(criterion, "DESC", orderBy, count, aliasTable, aliasCriterion); if (docList != null) { Set<Document> docSet = new TreeSet<Document>(new DocumentComparator()); docSet.addAll(docList); // First get all labels for the fetched documents labeledDocList = new ArrayList<HumanLabeledDocumentDTO>(); for (Document doc: docSet) { List<DocumentNominalLabelDTO> labeledDataDTO = remoteDocumentNominalLabelEJB.findLabeledDocumentListByID(doc.getDocumentId()); if (labeledDataDTO != null) { for (DocumentNominalLabelDTO dto: labeledDataDTO) { NominalLabelDTO nominalLabel = remoteNominalLabelEJB.getNominalLabelWithAllFieldsByID(dto.getIdDTO().getNominalLabelId()); if (nominalLabel != null) { nominalLabel.setDocumentNominalLabelsDTO(null); nominalLabel.setModelNominalLabelsDTO(null); } dto.setNominalLabelDTO(nominalLabel); dto.setDocumentDTO(null); } labeledDocList.add(new HumanLabeledDocumentDTO(new DocumentDTO(doc), labeledDataDTO)); } } return labeledDocList; } else { return null; } } catch (Exception e) { logger.error("Error in getting human labeled documents collection for crisisID: " + crisisID); logger.error("exception", e); } return null; } @Override public List<HumanLabeledDocumentDTO> getHumanLabeledDocumentsByCrisisCode(String crisisCode, Integer count) throws Exception{ if (null == crisisCode) { logger.error("crisis code can't be null"); throw new PropertyNotSetException("crisis code can't be null"); } CollectionDTO crisis = remoteCrisisEJB.getCrisisByCode(crisisCode); if (null == crisis) { logger.error("crisis code is invalid"); throw new PropertyNotSetException("crisis code is invalid"); } //logger.info("Received request for crisis code = " + crisisCode + ", count = " + count); return this.getHumanLabeledDocumentsByCrisisID(crisis.getCrisisID(), count); } @Override public List<HumanLabeledDocumentDTO> getHumanLabeledDocumentsByCrisisIDUserID(Long crisisID, Long userID, Integer count) throws Exception { if (null == crisisID || null == userID) { logger.error("crisis ID or userID can't be null"); throw new PropertyNotSetException("crisis ID or userID can't be null"); } //logger.info("Received request for crisisID = " + crisisID + ", userID = " + userID + ", count = " + count); List <HumanLabeledDocumentDTO> labeledDocList = null; String aliasTable = "documentNominalLabels"; String aliasTableKeyField = "documentNominalLabels.id.nominalLabelId"; String[] orderBy = {"documentId"}; Criterion criterion = Restrictions.conjunction() .add(Restrictions.eq("collection.id",crisisID)) .add(Restrictions.eq("hasHumanLabels", true)); Criterion aliasCriterion = Restrictions.conjunction() .add(Restrictions.isNotNull(aliasTableKeyField)) .add(Restrictions.eq("documentNominalLabels.id.userId", userID)); try { List<Document> docList = remoteDocumentEJB.getByCriteriaWithInnerJoinByOrder(criterion, "DESC", orderBy, count, aliasTable, aliasCriterion); if (docList != null) { Set<Document> docSet = new TreeSet<Document>(new DocumentComparator()); docSet.addAll(docList); // First get all labels for the fetched documents labeledDocList = new ArrayList<HumanLabeledDocumentDTO>(); for (Document doc: docSet) { List<DocumentNominalLabelDTO> labeledDataDTO = remoteDocumentNominalLabelEJB.findLabeledDocumentListByID(doc.getDocumentId()); if (labeledDataDTO != null) { for (DocumentNominalLabelDTO dto: labeledDataDTO) { NominalLabelDTO nominalLabel = remoteNominalLabelEJB.getNominalLabelWithAllFieldsByID(dto.getIdDTO().getNominalLabelId()); if (nominalLabel != null) { nominalLabel.setDocumentNominalLabelsDTO(null); nominalLabel.setModelNominalLabelsDTO(null); } dto.setNominalLabelDTO(nominalLabel); dto.setDocumentDTO(null); } labeledDocList.add(new HumanLabeledDocumentDTO(new DocumentDTO(doc), labeledDataDTO)); } } return labeledDocList; } else { return null; } } catch (Exception e) { logger.error("Error in getting human labeled documents collection for crisisID: " + crisisID); logger.error("exception", e); } return null; } @Override public List<HumanLabeledDocumentDTO> getHumanLabeledDocumentsByCrisisIDUserName(Long crisisID, String userName, Integer count) throws Exception { if (null == crisisID || null == userName) { logger.error("crisis ID or userName can't be null"); throw new PropertyNotSetException("crisis ID or userName can't be null"); } UsersDTO user = remoteUsersEJB.getUserByName(userName); if (null == user) { logger.error("User name is invalid"); throw new PropertyNotSetException("User name is invalid"); } //logger.info("Received request for crisisID = " + crisisID + ", userName = " + userName + ", count = " + count); return this.getHumanLabeledDocumentsByCrisisIDUserID(crisisID, user.getUserID(), count); } @Override public boolean deleteTask(Long crisisID, Long userID) { boolean success; try { List<DocumentDTO> documentDTOs = remoteDocumentEJB.findDocumentsByCrisisID(crisisID); if(documentDTOs != null && userID != null) { for(DocumentDTO documentDTO : documentDTOs) { remoteTaskAssignmentEJB.undoTaskAssignment(documentDTO.getDocumentID(), userID); remoteTaskAnswerEJB.deleteTaskAnswer(documentDTO.getDocumentID()); } } remoteDocumentEJB.deleteDocuments(documentDTOs); success = true; //logger.info("Successful deletion for task data."); } catch (Exception e) { logger.error("Unable to delete task for crisidID : " + crisisID + " and userID : " + userID); success = false; } return success; } @Override @Asynchronous public void importTrainingDataForClassifier(Long targetCollectionId, Long sourceCollectionId, Long nominalAttributeId) { try { List<Long> nominalLabelIds = remoteNominalLabelEJB.getNominalLabelIdsByAttributeID(nominalAttributeId); List<DocumentDTO> documentDTOs = remoteDocumentEJB.getDocumentForNominalLabelAndCrisis(nominalLabelIds, sourceCollectionId); CollectionDTO collectionDTO = remoteCrisisEJB.findCrisisByID(targetCollectionId); CollectionDTO sourceCollection = remoteCrisisEJB.findCrisisByID(sourceCollectionId); // save model family ModelFamilyDTO modelFamilyDTO = new ModelFamilyDTO(); modelFamilyDTO.setCrisisDTO(collectionDTO); NominalAttributeDTO attributeDTO = new NominalAttributeDTO(); attributeDTO.setNominalAttributeId(nominalAttributeId); modelFamilyDTO.setNominalAttributeDTO(attributeDTO); modelFamilyDTO.setIsActive(true); boolean success = modelFamilyResourceFacade.addCrisisAttribute(modelFamilyDTO); if(success) { // iterate through each tagged document for(DocumentDTO documentDTO : documentDTOs) { DocumentDTO documentToSave = new DocumentDTO(); documentToSave.setCrisisDTO(collectionDTO); documentToSave.setData(UnicodeEscaper.outsideOf(32, 0x7f).translate(documentDTO.getData())); documentToSave.setGeoFeatures(documentDTO.getGeoFeatures()); documentToSave.setDoctype(documentDTO.getDoctype()); documentToSave.setHasHumanLabels(true); documentToSave.setLanguage(documentDTO.getLanguage()); documentToSave.setWordFeatures(UnicodeEscaper.outsideOf(32, 0x7f).translate(documentDTO.getWordFeatures())); documentToSave.setValueAsTrainingSample(documentDTO.getValueAsTrainingSample()); documentToSave.setIsEvaluationSet(documentDTO.getIsEvaluationSet()); documentToSave.setReceivedAt(documentDTO.getReceivedAt()); documentToSave.setSourceCollection(sourceCollection); // save new document DocumentDTO newDocument = remoteDocumentEJB.addDocument(documentToSave); // fetch document nominal label for existing doc List<DocumentNominalLabelDTO> documentNominalLabelDTOs = remoteDocumentNominalLabelEJB.findLabeledDocumentListByID(documentDTO.getDocumentID()); // add new document labels if(documentNominalLabelDTOs != null) { for(DocumentNominalLabelDTO documentNominalLabelDTO : documentNominalLabelDTOs) { DocumentNominalLabelDTO labelDTOToSave = new DocumentNominalLabelDTO(); labelDTOToSave.setDocumentDTO(newDocument); labelDTOToSave.setNominalLabelDTO(documentNominalLabelDTO.getNominalLabelDTO()); labelDTOToSave.setIdDTO(new DocumentNominalLabelIdDTO(newDocument.getDocumentID(), documentNominalLabelDTO.getIdDTO().getNominalLabelId(), documentNominalLabelDTO.getIdDTO().getUserId())); this.saveDocumentNominalLabel(labelDTOToSave); } } // fetch task answers for existing doc List<TaskAnswerDTO> answers = remoteTaskAnswerEJB.getTaskAnswer(documentDTO.getDocumentID()); // save task answers for(TaskAnswerDTO answer : answers) { TaskAnswerDTO answerToSave = new TaskAnswerDTO(); answerToSave.setAnswer(answer.getAnswer()); answerToSave.setDocumentID(newDocument.getDocumentID()); answerToSave.setUserID(answer.getUserID()); answerToSave.setTimestamp(new Date()); remoteTaskAnswerEJB.insertTaskAnswer(answerToSave); } } } } catch (Exception e) { logger.error("Error in importing training data for collection id : " + sourceCollectionId + " and attribute : " + nominalAttributeId, e); } } private class DocumentComparator implements Comparator<Document> { @Override public int compare(Document d1, Document d2) { return d1.getDocumentId().compareTo(d2.getDocumentId()); } } }