Java tutorial
package elaborate.editor.model.orm.service; /* * #%L * elab4-backend * ======= * Copyright (C) 2011 - 2016 Huygens ING * ======= * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.io.IOException; import java.text.MessageFormat; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import org.apache.commons.lang.StringUtils; import org.hibernate.Hibernate; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import elaborate.editor.export.mvn.MVNAnnotationType; import elaborate.editor.export.pdf.PdfMaker; import elaborate.editor.export.tei.TagInfo; import elaborate.editor.export.tei.TeiConversionConfig; import elaborate.editor.export.tei.TeiMaker; import elaborate.editor.model.Action; import elaborate.editor.model.ProjectMetadataFields; import elaborate.editor.model.ProjectPrototype; import elaborate.editor.model.ProjectTypes; import elaborate.editor.model.orm.Annotation; import elaborate.editor.model.orm.AnnotationMetadataItem; import elaborate.editor.model.orm.AnnotationType; import elaborate.editor.model.orm.LogEntry; import elaborate.editor.model.orm.Project; import elaborate.editor.model.orm.ProjectEntry; import elaborate.editor.model.orm.ProjectEntryMetadataItem; import elaborate.editor.model.orm.ProjectMetadataItem; import elaborate.editor.model.orm.ProjectUser; import elaborate.editor.model.orm.Transcription; import elaborate.editor.model.orm.TranscriptionType; import elaborate.editor.model.orm.User; import elaborate.editor.publish.Publication; import elaborate.editor.publish.Publisher; import nl.knaw.huygens.Log; import nl.knaw.huygens.facetedsearch.SolrUtils; import nl.knaw.huygens.jaxrstools.exceptions.BadRequestException; import nl.knaw.huygens.jaxrstools.exceptions.UnauthorizedException; import nl.knaw.huygens.solr.FacetInfo; public class ProjectService extends AbstractStoredEntityService<Project> { private static final String PROJECT_NAME = "name"; private static final String PROJECT_TITLE = "Project title"; private static final String PROJECT_LEADER = "Project leader"; private static final String COUNT_KEY = "count"; private static final List<String> DEFAULT_PROJECTENTRYMETADATAFIELDNAMES = Lists.newArrayList(); private static ProjectService instance = new ProjectService(); private ProjectService() { } public static ProjectService instance() { return instance; } @Override Class<Project> getEntityClass() { return Project.class; } @Override String getEntityName() { return "Project"; } /* CRUD methods */ public Project create(ProjectPrototype projectPrototype, User user) { Project project = projectPrototype.getProject(); if (!rootOrAdmin(user)) { throw new UnauthorizedException("user " + user.getUsername() + " has no admin rights"); } else { addDefaultFields(project, user); beginTransaction(); Project created; try { created = super.create(project); String projectType = projectPrototype.getType(); ProjectMetadataItem pmi = project.addMetadata(ProjectMetadataFields.TYPE, projectType, user); persist(pmi); if (ProjectTypes.MVN.equals(projectType)) { project.setAnnotationTypes(mvnAnnotationTypes(getEntityManager(), user)); pmi = project.addMetadata(ProjectMetadataFields.TEXT_FONT, "junicode", user); persist(pmi); } persist(project); persist(created.addLogEntry("project created", user)); } finally { commitTransaction(); } return created; } } private Set<AnnotationType> mvnAnnotationTypes(EntityManager entityManager, User creator) { AnnotationTypeService annotationTypeService = AnnotationTypeService.instance(); annotationTypeService.setEntityManager(entityManager); Set<AnnotationType> set = Sets.newHashSet(); for (String name : MVNAnnotationType.getAllNames()) { AnnotationType annotationType = annotationTypeService.getAnnotationTypeByName(name, entityManager); if (annotationType != null) { set.add(annotationType); } else { Log.warn("missing MVN annotationtype: " + name); } } return set; } private void addDefaultFields(Project project, User user) { project.setCreator(user); project.setCreatedOn(new Date()); project.setModifier(user); project.setModifiedOn(new Date()); if (project.getTextLayers().length == 0) { project.setTextLayers(Lists.newArrayList(TranscriptionType.DIPLOMATIC)); } if (StringUtils.isBlank(project.getName())) { project.setName(SolrUtils.normalize(project.getTitle().replace("_", "-"))); } if (project.getProjectLeaderId() == 0) { project.setProjectLeaderId(user.getId()); } if (!project.getProjectEntryMetadataFieldnames().iterator().hasNext()) { project.setProjectEntryMetadataFieldnames(DEFAULT_PROJECTENTRYMETADATAFIELDNAMES); } if (project.getAnnotationTypes().isEmpty()) { AnnotationType default_annotationType = AnnotationTypeService.instance().getDefaultAnnotationType(); project.setAnnotationTypes(Sets.newHashSet(default_annotationType)); } } public Project read(long project_id, User user) { Project project; openEntityManager(); try { project = getProjectIfUserCanRead(project_id, user); } finally { closeEntityManager(); } return project; } public void update(Project project, User user) { beginTransaction(); try { super.update(project); setModifiedBy(project, user); } finally { commitTransaction(); } } public void delete(long project_id, User user) { beginTransaction(); try { super.delete(project_id); getSolrIndexer().deindexProject(project_id); Log.info("user {} deleting project {}", user.getUsername(), project_id); } finally { commitTransaction(); } } /* ---------------------------------------------------------------------------------------------------- */ public Collection<ProjectEntry> getProjectEntries(long id, User user) { List<ProjectEntry> projectEntriesInOrder; openEntityManager(); try { getProjectIfUserCanRead(id, user); projectEntriesInOrder = getProjectEntriesInOrder(id); } finally { closeEntityManager(); } return projectEntriesInOrder; } public Collection<Map<String, String>> getProjectEntryMetadata(long id, User user) { Collection<Map<String, String>> projectEntryMetadata = Lists.newArrayList(); openEntityManager(); try { Project project = getProjectIfUserCanRead(id, user); project.getProjectEntryMetadataFieldnames(); // select l1.data as bewaarplaats, // l2.data as collectie, // l3.data as signatuur, // l4.data as afzenders, // l5.data as ontvangers, // l6.data as datum // from project_entries e // left outer join project_entry_metadata_items l0 // on (l0.project_entry_id = e.id and l0.field='Scan(s)') // left outer join project_entry_metadata_items l1 // on (l1.project_entry_id = e.id and l1.field='Bewaarplaats') // left outer join project_entry_metadata_items l2 // on (l2.project_entry_id = e.id and l2.field='Collectie') // left outer join project_entry_metadata_items l3 // on (l3.project_entry_id = e.id and l3.field='Signatuur') // left outer join project_entry_metadata_items l4 // on (l4.project_entry_id = e.id and l4.field='Afzender(s)') // left outer join project_entry_metadata_items l5 // on (l5.project_entry_id = e.id and l5.field='Ontvanger(s)') // left outer join project_entry_metadata_items l6 // on (l6.project_entry_id = e.id and l6.field='Datum') // where e.project_id = 44 and l0.data='' // order by l0.data,l1.data, l2.data, l3.data ,l4.data, l5.data, l6.data; List<ProjectEntry> projectEntriesInOrder = getProjectEntriesInOrder(id); for (ProjectEntry projectEntry : projectEntriesInOrder) { Map<String, String> metadata = Maps.newHashMap(); metadata.put("entryname", projectEntry.getName()); List<ProjectEntryMetadataItem> projectEntryMetadataItems = projectEntry .getProjectEntryMetadataItems(); for (ProjectEntryMetadataItem projectEntryMetadataItem : projectEntryMetadataItems) { metadata.put(projectEntryMetadataItem.getField(), projectEntryMetadataItem.getData()); } projectEntryMetadata.add(metadata); } } finally { closeEntityManager(); } return projectEntryMetadata; } public List<ProjectEntry> getProjectEntriesInOrder0(long id) { find(getEntityClass(), id); List<ProjectEntry> resultList = getEntityManager()// . .createQuery("from ProjectEntry pe" + // " where project_id=:projectId" + // " order by pe.name", // ProjectEntry.class)// .setParameter("projectId", id)// .getResultList(); ImmutableList<ProjectEntry> projectEntries = ImmutableList.copyOf(resultList); return projectEntries; } public List<ProjectEntry> getProjectEntriesInOrder(long id) { final List<Long> projectEntryIdsInOrder = getProjectEntryIdsInOrder(id); Project project = find(getEntityClass(), id); List<ProjectEntry> projectEntries = project.getProjectEntries(); Collections.sort(projectEntries, new Comparator<ProjectEntry>() { @Override public int compare(ProjectEntry e1, ProjectEntry e2) { return projectEntryIdsInOrder.indexOf(e1.getId())// - projectEntryIdsInOrder.indexOf(e2.getId()); } }); return projectEntries; } public List<Long> getProjectEntryIdsInOrder(long id) { Project project = find(getEntityClass(), id); List<Long> resultList = getEntityManager()// . .createQuery("select pe.id from ProjectEntry pe" + // " left join pe.projectEntryMetadataItems l1 with l1.field=:level1" + // " left join pe.projectEntryMetadataItems l2 with l2.field=:level2" + // " left join pe.projectEntryMetadataItems l3 with l3.field=:level3" + // " where project_id=:projectId" + // " order by l1.data,l2.data,l3.data,pe.name", // Long.class)// .setParameter("level1", project.getLevel1())// .setParameter("level2", project.getLevel2())// .setParameter("level3", project.getLevel3())// .setParameter("projectId", id)// .getResultList(); ImmutableList<Long> projectEntryIds = ImmutableList.copyOf(resultList); return projectEntryIds; } public ProjectEntry createProjectEntry(long id, ProjectEntry projectEntry, User user) { beginTransaction(); ProjectEntry entry; try { Project project = find(getEntityClass(), id); entry = project.addEntry(projectEntry.getName(), user); persist(entry); setModifiedBy(entry, user); String[] textLayers = project.getTextLayers(); for (String textLayer : textLayers) { Transcription transcription = entry.addTranscription(user).setTextLayer(textLayer); persist(transcription); } persist(project.addLogEntry("added entry " + projectEntry.getName(), user)); } finally { commitTransaction(); } return entry; } private static final Comparator<Project> SORT_PROJECTS = new Comparator<Project>() { @Override public int compare(Project p1, Project p2) { return p2.getModifiedOn().compareTo(p1.getModifiedOn()); } }; public List<Project> getAll(User user) { List<Project> projects; openEntityManager(); try { if (rootOrAdmin(user)) { projects = Lists.newArrayList(super.getAll()); } else { projects = getProjectsForUser(user); } Collections.sort(projects, SORT_PROJECTS); } finally { closeEntityManager(); } return projects; } public Map<String, String> getProjectSettings(long project_id, User user) { Map<String, String> map = Maps.newHashMap(); openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); Hibernate.initialize(project); List<ProjectMetadataItem> projectMetadataItems = project.getProjectMetadataItems(); Hibernate.initialize(projectMetadataItems); for (ProjectMetadataItem projectMetadataItem : projectMetadataItems) { Hibernate.initialize(projectMetadataItem); map.put(projectMetadataItem.getField(), projectMetadataItem.getData()); } map.put(PROJECT_TITLE, project.getTitle()); map.put(PROJECT_NAME, project.getName().replace("_", "-")); map.put(PROJECT_LEADER, String.valueOf(project.getProjectLeaderId())); } finally { closeEntityManager(); } return map; } /* private methods */ // Throws Unauthorized acception when user has no read access rights to the project with id project_id Project getProjectIfUserCanRead(long project_id, User user) { if (rootOrAdmin(user)) { return super.read(project_id); } Project project = null; List<ProjectUser> resultList = getEntityManager()// .createQuery("from ProjectUser where user_id=:userId and project_id=:projectId", ProjectUser.class)// .setParameter("userId", user.getId())// .setParameter("projectId", project_id)// .getResultList(); // logMemory(); if (!resultList.isEmpty()) { project = resultList.get(0).getProject(); Hibernate.initialize(project); } if (project == null) { closeEntityManager(); throw new UnauthorizedException( "user " + user.getUsername() + " has no read permission for project with id " + project_id); } return project; } private List<Project> getProjectsForUser(User user) { TypedQuery<ProjectUser> createQuery = getEntityManager() .createQuery("from ProjectUser where user_id=:userId", ProjectUser.class) .setParameter("userId", user.getId()); List<ProjectUser> resultList = createQuery.getResultList(); ImmutableList<ProjectUser> projectUsers = ImmutableList.copyOf(resultList); List<Project> projects = Lists.newArrayList(); logMemory(); for (ProjectUser projectUser : projectUsers) { Project project = projectUser.getProject(); Hibernate.initialize(project); projects.add(project); } return projects; } void logMemory() { int mb = 1024 * 1024; System.gc(); // Getting the runtime reference from system Runtime runtime = Runtime.getRuntime(); Log.info("##### Heap utilization statistics [MB] #####"); // Print used memory Log.info("Used Memory:" + (runtime.totalMemory() - runtime.freeMemory()) / mb); // Print free memory Log.info("Free Memory:" + runtime.freeMemory() / mb); // Print total available memory Log.info("Total Memory:" + runtime.totalMemory() / mb); // Print Maximum available memory Log.info("Max Memory:" + runtime.maxMemory() / mb); } public Iterable<String> getProjectEntryMetadataFields(long project_id, User user) { openEntityManager(); Iterable<String> projectEntryMetadataFieldnames; try { Project project = getProjectIfUserCanRead(project_id, user); projectEntryMetadataFieldnames = project.getProjectEntryMetadataFieldnames(); } finally { closeEntityManager(); } return projectEntryMetadataFieldnames; } public void setProjectEntryMetadataFields(long project_id, List<String> fields, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); project.setProjectEntryMetadataFieldnames(fields); persist(project); persist(project.addLogEntry("projectentrymetadatafields changed", user)); setModifiedBy(project, user); } finally { commitTransaction(); } } public Object getProjectAnnotationTypes(long project_id, User user) { Set<AnnotationType> annotationTypes; openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); annotationTypes = project.getAnnotationTypes(); } finally { closeEntityManager(); } return annotationTypes; } public List<Long> getProjectAnnotationTypeIds(long project_id, User user) { List<Long> list = Lists.newArrayList(); openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); for (AnnotationType annotationType : project.getAnnotationTypes()) { list.add(annotationType.getId()); } } finally { closeEntityManager(); } return list; } public void setProjectAnnotationTypes(long project_id, List<Long> annotationTypeIds, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); Set<AnnotationType> annotationTypes = Sets.newHashSet(); for (Long id : annotationTypeIds) { AnnotationType at = getEntityManager().find(AnnotationType.class, id); annotationTypes.add(at); } project.setAnnotationTypes(annotationTypes); persist(project.addLogEntry("projectannotationtypes changed", user)); setModifiedBy(project, user); } finally { commitTransaction(); } } public void setProjectAnnotationTypes(long project_id, Set<AnnotationType> annotationTypes, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); project.setAnnotationTypes(annotationTypes); persist(project.addLogEntry("projectannotationtypes changed", user)); setModifiedBy(project, user); } finally { commitTransaction(); } } public Map<String, Object> getProjectStatistics(long project_id, User user) { removeOrphanedAnnotations(project_id); openEntityManager(); Map<String, Object> statistics; try { Project project = getProjectIfUserCanRead(project_id, user); statistics = ImmutableMap.<String, Object>of("entries", getProjectEntriesStatistics(project_id, getEntityManager(), project)); } finally { closeEntityManager(); } return statistics; } private Map<String, Object> getProjectEntriesStatistics(long project_id, EntityManager entityManager, Project project) { Long transcriptionCount = getTranscriptionCount(project_id, entityManager); // Long annotationCount = getAnnotationCount(project_id, entityManager); Long facsimileCount = getFacsimileCount(project_id, entityManager); Map<String, Object> textLayerCountMap = getTextLayerCountMap(project_id, entityManager, project); Map<String, Object> transcriptionStatistics = Maps.newHashMap(); transcriptionStatistics.put(COUNT_KEY, transcriptionCount); transcriptionStatistics.put("textlayers", textLayerCountMap); Map<String, Object> annotationTypeCountMap = getAnnotationTypeCountMap(project_id, entityManager, project); Map<String, Object> annotationStatistics = Maps.newHashMap(); annotationStatistics.put("annotationtypes", annotationTypeCountMap); Collection<Object> values = annotationTypeCountMap.values(); int annotationCount = 0; for (Object typecount : values) { annotationCount += (Long) typecount; } annotationStatistics.put(COUNT_KEY, annotationCount); Map<String, Object> parts = Maps.newHashMap(); parts.put("transcriptions", transcriptionStatistics); parts.put("annotations", annotationStatistics); parts.put("facsimiles", facsimileCount); Map<String, Object> entriesStatistics = Maps.newHashMap(); entriesStatistics.put(COUNT_KEY, getEntriesCount(project_id, entityManager)); entriesStatistics.put("parts", parts); return entriesStatistics; } private Long getTranscriptionCount(long project_id, EntityManager entityManager) { Long transcriptionCount = (Long) entityManager// .createQuery("select count(*) from Transcription"// + " where project_entry_id in"// + " (select id from ProjectEntry where project_id=:project_id)"// )// .setParameter("project_id", project_id)// .getSingleResult(); return transcriptionCount; } // private Long getAnnotationCount(long project_id, EntityManager entityManager) { // Long annotationCount = (Long) entityManager// // .createQuery("select count(*) from Annotation"// // + " where transcription_id in"// // + " (select id from Transcription"// // + " where project_entry_id in"// // + " (select id from ProjectEntry where project_id=:project_id))"// // )// // .setParameter("project_id", project_id)// // .getSingleResult(); // return annotationCount; // } private Long getFacsimileCount(long project_id, EntityManager entityManager) { Long facsimileCount = (Long) entityManager// .createQuery("select count(*) from"// + " Facsimile where project_entry_id in"// + " (select id from ProjectEntry where project_id=:project_id)"// )// .setParameter("project_id", project_id)// .getSingleResult(); return facsimileCount; } private Map<String, Object> getTextLayerCountMap(long project_id, EntityManager entityManager, Project project) { Map<String, Object> textLayerCountMap = Maps.newHashMap(); for (String textLayer : project.getTextLayers()) { Long textLayerCount = (Long) entityManager// .createQuery("select count(*) from Transcription"// + " where text_layer = :text_layer"// + " and project_entry_id in"// + " (select id from ProjectEntry where project_id=:project_id)"// )// .setParameter("text_layer", textLayer)// .setParameter("project_id", project_id)// .getSingleResult(); textLayerCountMap.put(textLayer, textLayerCount); } return textLayerCountMap; } private Map<String, Object> getAnnotationTypeCountMap(long project_id, EntityManager entityManager, Project project) { Map<String, Object> annotationTypeCountMap = Maps.newHashMap(); for (AnnotationType annotationType : project.getAnnotationTypes()) { Long annotationTypeCount = (Long) entityManager// .createQuery("select count(*) from Annotation"// + " where annotation_type_id = :annotation_type_id"// + " and transcription_id in"// + " (select id from Transcription"// + " where project_entry_id in"// + " (select id from ProjectEntry where project_id=:project_id))"// )// .setParameter("annotation_type_id", annotationType.getId())// .setParameter("project_id", project_id)// .getSingleResult(); annotationTypeCountMap.put(annotationType.getName(), annotationTypeCount); } return annotationTypeCountMap; } private Long getEntriesCount(long project_id, EntityManager entityManager) { Long entriesCount = (Long) entityManager// .createQuery("select count(*) from ProjectEntry"// + " where project_id=:project_id"// )// .setParameter("project_id", project_id)// .getSingleResult(); return entriesCount; } public List<FacetInfo> getFacetInfo(long project_id, User user) { openEntityManager(); List<FacetInfo> list; try { Project project = getProjectIfUserCanRead(project_id, user); list = ImmutableList.copyOf(project.getFacetInfo()); } finally { closeEntityManager(); } return list; } public void setTextlayers(long project_id, List<String> textLayers, User user) { beginTransaction(); Set<Long> modifiedEntryIds = Sets.newHashSet(); try { Project project = getProjectIfUserCanRead(project_id, user); List<String> previous = Lists.newArrayList(project.getTextLayers()); List<String> deletedTextLayers = previous; deletedTextLayers.removeAll(textLayers); project.setTextLayers(textLayers); persist(project); persist(project.addLogEntry("project textlayers changed", user)); setModifiedBy(project, user); if (!deletedTextLayers.isEmpty()) { persist(project.addLogEntry("removing textlayer(s) " + Joiner.on(", ").join(deletedTextLayers), user)); for (String textlayer : deletedTextLayers) { List<?> resultList = getEntityManager()// .createQuery( "select e.id, t.id from ProjectEntry e join e.transcriptions as t with t.text_layer=:textlayer where e.project=:project")// .setParameter("project", project)// .setParameter("textlayer", textlayer)// .getResultList(); for (Object object : resultList) { Object[] ids = (Object[]) object; Transcription transcription = getEntityManager().find(Transcription.class, ids[1]); remove(transcription); modifiedEntryIds.add((Long) ids[0]); } } } } finally { commitTransaction(); } beginTransaction(); try { for (Long id : modifiedEntryIds) { ProjectEntry entry = getEntityManager().find(ProjectEntry.class, id); setModifiedBy(entry, user); } } finally { commitTransaction(); } } public void setProjectSettings(long project_id, Map<String, String> settingsMap, User user) { Long userId = -1l; beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); if (!user.getPermissionFor(project).can(Action.EDIT_PROJECT_SETTINGS)) { throw new UnauthorizedException("user " + user.getUsername() + " has no projectsettings permission for project " + project.getName()); } List<ProjectMetadataItem> projectMetadataItems = project.getProjectMetadataItems(); for (ProjectMetadataItem projectMetadataItem : projectMetadataItems) { getEntityManager().remove(projectMetadataItem); } for (Entry<String, String> entry : settingsMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); ProjectMetadataItem pmi = project.addMetadata(key, value, user); if (PROJECT_TITLE.equals(key)) { project.setTitle(value); } else if (PROJECT_NAME.equals(key)) { project.setName(value); } else if (PROJECT_LEADER.equals(key)) { userId = Long.valueOf(value); project.setProjectLeaderId(userId); } persist(pmi); } persist(project); persist(project.addLogEntry("projectsettings changed", user)); setModifiedBy(project, user); } finally { commitTransaction(); if (userId > -1) { UserService userService = UserService.instance(); userService.makeProjectLeader(userId, user); } } } public Set<User> getProjectUsersFull(long project_id, User user) { openEntityManager(); Set<User> projectUsers; try { Project project = getProjectIfUserCanRead(project_id, user); projectUsers = project.getUsers(); Hibernate.initialize(projectUsers); } finally { closeEntityManager(); } return projectUsers; } public List<Long> getProjectUserIds(long project_id, User user) { List<Long> list = Lists.newArrayList(); openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); for (User pUser : project.getUsers()) { list.add(pUser.getId()); } } finally { closeEntityManager(); } return list; } public User addProjectUser(long project_id, long user_id, User user) { beginTransaction(); User projectUser; try { Project project = getProjectIfUserCanRead(project_id, user); projectUser = getProjectUser(user_id); project.getUsers().add(projectUser); persist(project); persist(project.addLogEntry("user " + projectUser.getUsername() + " added to project", user)); setModifiedBy(project, user); } finally { commitTransaction(); } return projectUser; } public void deleteProjectUser(long project_id, long user_id, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); User projectUser = getProjectUser(user_id); project.getUsers().remove(projectUser); persist(project); persist(project.addLogEntry("user " + projectUser.getUsername() + " removed from project", user)); setModifiedBy(project, user); } finally { commitTransaction(); } } private User getProjectUser(long user_id) { User projectUser = find(User.class, user_id); if (projectUser == null) { throw new BadRequestException("no user found with id " + user_id); } return projectUser; } public List<LogEntry> getLogEntries(long project_id, User user) { openEntityManager(); List<LogEntry> logEntries; try { Project project = getProjectIfUserCanRead(project_id, user); logEntries = Ordering.natural().sortedCopy(project.getLogEntries()); } finally { closeEntityManager(); } return logEntries; } public String exportTei(long project_id, User user) { String tei; openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); AnnotationType versregels = getEntityManager() .createQuery("from AnnotationType where name=:name", AnnotationType.class) .setParameter("name", "versregel").getSingleResult(); tei = exportTei(project, null, versregels); } finally { closeEntityManager(); } return tei; } public void exportPdf(long project_id, User user, String filename) { openEntityManager(); try { Project project = getProjectIfUserCanRead(project_id, user); PdfMaker pdfMaker = new PdfMaker(project, getEntityManager()); pdfMaker.saveToFile(filename); } finally { closeEntityManager(); } } public Publication.Status createPublicationStatus(long project_id, User user) { Publisher publisher = Publisher.instance(); boolean canPublish; Project project; Map<String, String> projectMetadata; openEntityManager(); try { project = getProjectIfUserCanRead(project_id, user); canPublish = user.getPermissionFor(project).can(Action.PUBLISH); projectMetadata = project.getMetadataMap(); } finally { closeEntityManager(); } if (!canPublish) { throw new UnauthorizedException(MessageFormat.format("{0} has no publishing permission for {1}", user.getUsername(), project.getTitle())); } ; String projectType = StringUtils.defaultIfBlank(projectMetadata.get(ProjectMetadataFields.TYPE), ProjectTypes.COLLECTION); List<Long> publishableAnnotationTypeIds = getPublishableAnnotationTypeIds(projectMetadata); List<String> publishableProjectEntryMetadataFields = getPublishableProjectEntryMetadataFields( projectMetadata); List<String> facetableProjectEntryMetadataFields = getFacetableProjectEntryMetadataFields(projectMetadata); List<String> publishableTextLayers = getPublishableTextLayers(projectMetadata); Publication.Settings settings = new Publication.Settings()// .setProjectId(project_id)// .setUser(user)// .setTextLayers(publishableTextLayers)// .setAnnotationTypeIds(publishableAnnotationTypeIds)// .setProjectEntryMetadataFields(publishableProjectEntryMetadataFields)// .setFacetFields(facetableProjectEntryMetadataFields)// .setProjectType(projectType); Publication.Status publicationStatus = publisher.publish(settings); return publicationStatus; } private List<String> getPublishableTextLayers(Map<String, String> projectMetadata) { return deserialize(projectMetadata, ProjectMetadataFields.PUBLISHABLE_TEXT_LAYERS); } private List<String> getPublishableProjectEntryMetadataFields(Map<String, String> projectMetadata) { return deserialize(projectMetadata, ProjectMetadataFields.PUBLISHABLE_PROJECT_ENTRY_METADATA_FIELDS); } private List<String> getFacetableProjectEntryMetadataFields(Map<String, String> projectMetadata) { return deserialize(projectMetadata, ProjectMetadataFields.FACETABLE_PROJECT_ENTRY_METADATA_FIELDS); } @SuppressWarnings("unchecked") private List<String> deserialize(Map<String, String> projectMetadata, String key) { String metadataString = projectMetadata.get(key); List<String> list = Lists.newArrayList(); if (metadataString != null) { try { list = new ObjectMapper().readValue(metadataString, List.class); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return list; } private List<Long> getPublishableAnnotationTypeIds(Map<String, String> projectMetadata) { String metadataString = projectMetadata.get(ProjectMetadataFields.PUBLISHABLE_ANNOTATION_TYPE_IDS); List<Long> publishableAnnotationTypeIds = Lists.newArrayList(); if (metadataString != null) { try { publishableAnnotationTypeIds = new ObjectMapper().readValue(metadataString, new TypeReference<List<Long>>() { }); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return publishableAnnotationTypeIds; } public Publication.Status getPublicationStatus(String status_id) { Publisher publisher = Publisher.instance(); return publisher.getStatus(status_id); } /** private **/ private String exportTei(Project project, String groupTextsByMetadata, AnnotationType versregels) { Function<Annotation, TagInfo> mapToL = new Function<Annotation, TagInfo>() { @Override public TagInfo apply(Annotation annotation) { TagInfo tagInfo = new TagInfo().setName("l")/* .setSkipNewlineAfter(true) */; for (AnnotationMetadataItem annotationMetadataItem : annotation.getAnnotationMetadataItems()) { String name = annotationMetadataItem.getAnnotationTypeMetadataItem().getName(); String value = annotationMetadataItem.getData(); if ("n".equals(name)) { tagInfo.addAttribute("n", value); } else if ("inspringen".equals(name)) { tagInfo.addAttribute("rend", "indent"); } } return tagInfo; } }; TeiConversionConfig config = new TeiConversionConfig()// .setGroupTextsByMetadata(groupTextsByMetadata)// .addAnnotationTypeMapping(versregels, mapToL); String xml; openEntityManager(); try { xml = new TeiMaker(project, config, getEntityManager()).toXML(); } finally { closeEntityManager(); } return xml; } public void updateProjectUserIds(long project_id, List<Long> userIds, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); Set<User> users = Sets.newHashSet(); for (Long userId : userIds) { User puser = getProjectUser(userId); users.add(puser); } Set<User> prevUsers = project.getUsers(); String diff = getDiff(prevUsers, users); project.setUsers(users); persist(project.addLogEntry("projectusers changed: " + diff, user)); setModifiedBy(project, user); } finally { commitTransaction(); } } private String getDiff(Set<User> prevUsers, Set<User> users) { List<String> added = Lists.newArrayList(); for (User user : users) { if (!prevUsers.contains(user)) { added.add(user.getUsername()); } } List<String> deleted = Lists.newArrayList(); for (User user : prevUsers) { if (!users.contains(user)) { deleted.add(user.getUsername()); } } // updateProjectUserIds is called on every single add/delete, so only 1 add or del should be found. if (!added.isEmpty()) { return "user " + added.get(0) + " added"; } else if (!deleted.isEmpty()) { return "user " + deleted.get(0) + " removed"; } return ""; } public void setMetadata(long project_id, String key, String value, User user) { beginTransaction(); try { Project project = getProjectIfUserCanRead(project_id, user); ProjectMetadataItem item = null; List<ProjectMetadataItem> projectMetadataItems = project.getProjectMetadataItems(); for (ProjectMetadataItem projectMetadataItem : projectMetadataItems) { if (projectMetadataItem.getField().equals(key)) { item = projectMetadataItem; break; } } if (item == null) { ProjectMetadataItem pmi = project.addMetadata(key, value, user); persist(pmi); } else { item.setData(value); persist(item); } } finally { commitTransaction(); } } public void setProjectSortLevels(long project_id, List<String> levels, User user) { beginTransaction(); Project project = getProjectIfUserCanRead(project_id, user); if (!user.getPermissionFor(project).can(Action.EDIT_PROJECT_SETTINGS)) { throw new UnauthorizedException("user " + user.getUsername() + " has no projectsettings permission for project " + project.getName()); } List<String> newLevels = Lists.newArrayList("", "", ""); List<String> allowed = ImmutableList.copyOf(project.getProjectEntryMetadataFieldnames()); List<String> disallowed = Lists.newArrayListWithCapacity(3); for (int i = 0; i < 3; i++) { if (levels.size() > i) { String level = levels.get(i); newLevels.add(i, level); if (StringUtils.isNotBlank(level) && !allowed.contains(level)) { disallowed.add(level); } } } if (disallowed.isEmpty()) { project.setLevel1(newLevels.get(0)).setLevel2(newLevels.get(1)).setLevel3(newLevels.get(2)); persist(project); commitTransaction(); } else { rollbackTransaction(); throw new BadRequestException("invalid sortlevel value(s): " + Joiner.on(", ").join(disallowed)); } } public ReindexStatus createReindexStatus(long project_id) { openEntityManager(); try { read(project_id); } finally { closeEntityManager(); } ReindexStatus status = new ReindexStatus(); return status; } /** * Remove annotations that have no corresponding annotationmarkers (begin and end) in the Transcription Body * * @param modifier * The User credited with the removal */ public void removeOrphanedAnnotations(long project_id) { beginTransaction(); Project project = read(project_id); TranscriptionService transcriptionService = TranscriptionService.instance(); transcriptionService.setEntityManager(getEntityManager()); for (ProjectEntry projectEntry : project.getProjectEntries()) { for (Transcription transcription : projectEntry.getTranscriptions()) { transcriptionService.removeOrphanedAnnotations(transcription); } } commitTransaction(); } // public Map<Integer, String> getAnnotationTypesForProject(Long projectId) { // Map<Integer, String> annotationTypes = Maps.newHashMap(); // Project project = read(projectId); // List<?> resultList = getEntityManager()// // .createQuery("select a.annotationNo, at.name from Annotation as a inner join a.annotationType as at where a.transcription.projectEntry.project=:project")// // .setParameter("project", project)// // .getResultList(); // for (Object result : resultList) { // Object[] objects = (Object[]) result; // annotationTypes.put((Integer) objects[0], (String) objects[1]); // } // // return annotationTypes; // } // // public Map<Integer, Map<String, String>> getAnnotationParametersForProject(Long projectId) { // Map<Integer, Map<String, String>> annotationParameters = Maps.newHashMap(); // Project project = read(projectId); // List<?> resultList = getEntityManager()// // .createQuery("select a.annotationNo, am.annotationTypeMetadataItem.name, am.data from Annotation as a join a.annotationMetadataItems as am where a.transcription.projectEntry.project=:project")// // .setParameter("project", project)// // .getResultList(); // for (Object result : resultList) { // Object[] objects = (Object[]) result; // Integer annotationNo = (Integer) objects[0]; // Map<String, String> map = annotationParameters.get(annotationNo); // if (map == null) { // map = Maps.newHashMap(); // annotationParameters.put(annotationNo, map); // } // map.put((String) objects[1], (String) objects[2]); // } // return annotationParameters; // } public Map<Integer, AnnotationData> getAnnotationDataForProject(Long projectId) { beginTransaction(); Project project = read(projectId); Map<Integer, AnnotationData> annotationDataMap = Maps.newHashMap(); List<?> resultList = getEntityManager()// .createQuery( "select a.annotationNo, at.id, at.name from Annotation as a inner join a.annotationType as at where a.transcription.projectEntry.project=:project")// .setParameter("project", project)// .getResultList(); for (Object result : resultList) { Object[] objects = (Object[]) result; Integer annotationId = (Integer) objects[0]; Long annotationTypeId = (Long) objects[1]; String annotationType = (String) objects[2]; annotationDataMap.put(annotationId, new AnnotationData().setType(annotationType).setTypeId(annotationTypeId)); } resultList = getEntityManager()// .createQuery( "select a.annotationNo, am.annotationTypeMetadataItem.name, am.data from Annotation as a join a.annotationMetadataItems as am where a.transcription.projectEntry.project=:project")// .setParameter("project", project)// .getResultList(); for (Object result : resultList) { Object[] objects = (Object[]) result; Integer annotationNo = (Integer) objects[0]; String parameterKey = (String) objects[1]; String parameterValue = (String) objects[2]; annotationDataMap.get(annotationNo).getParameters().put(parameterKey, parameterValue); } rollbackTransaction(); // since it's read-only return annotationDataMap; } public static class AnnotationData { Long typeId; String type; Map<String, String> parameters = Maps.newHashMap(); public Long getTypeId() { return typeId; } public AnnotationData setTypeId(Long typeId) { this.typeId = typeId; return this; } public String getType() { return type; } public AnnotationData setType(String type) { this.type = type; return this; } public Map<String, String> getParameters() { return parameters; } public AnnotationData setParameters(Map<String, String> parameters) { this.parameters = parameters; return this; } } }