/* * Copyright 2017 * Ubiquitous Knowledge Processing (UKP) Lab and FG Language Technology * Technische Universität Darmstadt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.tudarmstadt.ukp.clarin.webanno.api; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import javax.persistence.NoResultException; import org.apache.uima.UIMAException; import org.apache.uima.cas.CAS; import org.apache.uima.cas.CASException; import org.apache.uima.jcas.JCas; import org.apache.uima.resource.ResourceInitializationException; import org.springframework.security.access.prepost.PreAuthorize; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocument; import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationDocumentState; import de.tudarmstadt.ukp.clarin.webanno.model.Mode; import de.tudarmstadt.ukp.clarin.webanno.model.Project; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocumentState; import de.tudarmstadt.ukp.clarin.webanno.security.model.User; public interface DocumentService { static final String SERVICE_NAME = "documentService"; /** * The Directory where the {@link SourceDocument}s and {@link AnnotationDocument}s stored * * @return the directory. */ File getDir(); /** * Load the CAS for the specified source document and user, upgrade it, and save it again. * Depending on the mode parameter, the automation/correction and curation CASes are also * upgraded. * * @param aDocument * the source document. * @param aMode * the mode. * @param username * the username. * @throws IOException * if an I/O error occurs. * @deprecated Read CAS e.g. using {@link #readAnnotationCas(SourceDocument, User)} then use  * {@link #upgradeCas(CAS, AnnotationDocument)} and then write the CAS e.g. using * {@link #writeAnnotationCas(JCas, SourceDocument, User, boolean)} */ @Deprecated void upgradeCasAndSave(SourceDocument aDocument, Mode aMode, String username) throws IOException; // -------------------------------------------------------------------------------------------- // Methods related to SourceDocuments // -------------------------------------------------------------------------------------------- /** * Creates a {@link SourceDocument} in a database. The source document is created by ROLE_ADMIN * or Project admins. Source documents are created per project and it should have a unique name * in the {@link Project} it belongs. renaming a a source document is not possible, rather the * administrator should delete and re create it. * * @param document * {@link SourceDocument} to be created * @throws IOException * if an I/O error occurs. */ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER','ROLE_REMOTE')") void createSourceDocument(SourceDocument document) throws IOException; /** * Check if a Source document with this same name exist in the project. The caller method then * can decide to override or throw an exception/message to the client * * @param project * the project. * @param fileName * the source document name. * @return if the source document exists. */ boolean existsSourceDocument(Project project, String fileName); /** * Get meta data information about {@link SourceDocument} from the database. This method is * called either for {@link AnnotationDocument} object creation or * {@link #createSourceDocument(SourceDocument)} * * @param project * the {@link Project} where the {@link SourceDocument} belongs * @param documentName * the name of the {@link SourceDocument} * @return the source document. */ SourceDocument getSourceDocument(Project project, String documentName); /** * Get meta data information about {@link SourceDocument} from the database. * * @param projectId * the id for the {@link Project} * @param documentId * the id for the {@link SourceDocument} * @return the source document */ SourceDocument getSourceDocument(long projectId, long documentId); /** * Return the Master TCF file Directory path. For the first time, all available TCF layers will * be read and converted to CAS object. subsequent accesses will be to the annotated document * unless and otherwise the document is removed from the project. * * @param document * The {@link SourceDocument} to be examined * @return the Directory path of the source document */ File getSourceDocumentFile(SourceDocument document); /** * List all source documents in a project. The source documents are the original TCF documents * imported. * * @param aProject * The Project we are looking for source documents * @return list of source documents */ List<SourceDocument> listSourceDocuments(Project aProject); /** * ROLE_ADMINs or project admins can remove source documents from a project. removing a a source * document also removes an annotation document related to that document * * @param document * the source document to be deleted * @throws IOException * If the source document searched for deletion is not available */ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER', 'ROLE_REMOTE')") void removeSourceDocument(SourceDocument document) throws IOException; @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER','ROLE_REMOTE')") void uploadSourceDocument(File file, SourceDocument document) throws IOException, UIMAException; /** * Upload a SourceDocument, obtained as Inputstream, such as from remote API Zip folder to a * repository directory. This way we don't need to create the file to a temporary folder * * @param file * the file. * @param document * the source document. * @throws IOException * if an I/O error occurs. * @throws UIMAException * if a conversion error occurs. */ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER','ROLE_REMOTE')") void uploadSourceDocument(InputStream file, SourceDocument document) throws IOException, UIMAException; /** * Get the directory of this {@link SourceDocument} usually to read the content of the document * * @param aDocument * the source document. * @return the source document folder. * @throws IOException * if an I/O error occurs. */ File getDocumentFolder(SourceDocument aDocument) throws IOException; // -------------------------------------------------------------------------------------------- // Methods related to AnnotationDocuments // -------------------------------------------------------------------------------------------- /** * creates the {@link AnnotationDocument } object in the database. * * @param annotationDocument * {@link AnnotationDocument} comprises of the the name of the {@link SourceDocument} * , id of {@link SourceDocument}, id of the {@link Project}, and id of {@link User} */ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')") void createAnnotationDocument(AnnotationDocument annotationDocument); /** * Creates an annotation document. The {@link AnnotationDocument} is stored in the * webanno.home/project/Project.id/document/document.id/annotation/username.ser. annotated * documents are stored per project, user and document * * @param jCas * the JCas. * @param document * the source document. * @param user * The User who perform this operation * @throws IOException * if an I/O error occurs. */ @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')") void writeAnnotationCas(JCas jCas, SourceDocument document, User user, boolean aUpdateTimestamp) throws IOException; /** * A Method that checks if there is already an annotation document created for the source * document * * @param document * the source document. * @param user * the user. * @return if an annotation document metadata exists for the user. */ boolean existsAnnotationDocument(SourceDocument document, User user); /** * check if the JCAS for the {@link User} and {@link SourceDocument} in this {@link Project} * exists It is important as {@link AnnotationDocument} entry can be populated as * {@link AnnotationDocumentState#NEW} from the MonitoringPage before the user actually open the * document for annotation. * * @param sourceDocument * the source document. * @param username * the username. * @return if an annotation document file exists. * @throws IOException * if an I/O error occurs. */ boolean existsCas(SourceDocument sourceDocument, String username) throws IOException; /** * Export a Serialized CAS annotation document from the file system * * @param document * the source document. * @param user * the username. * @return the serialized CAS file. */ File getCasFile(SourceDocument document, String user); /** * Get the annotation document. * * @param document * the source document. * @param user * the user. * @return the annotation document. * @throws NoResultException * if no annotation document exists for the given source/user. */ AnnotationDocument getAnnotationDocument(SourceDocument document, User user); /** * Gets the CAS for the given annotation document. Converts it form the source document if * necessary. * * @param annotationDocument * the annotation document. * @return the JCas. * @throws IOException * if there was an I/O error. */ JCas readAnnotationCas(AnnotationDocument annotationDocument) throws IOException; /** * Gets the CAS for the given annotation document. Converts it form the source document if * necessary. If necessary, no annotation document exists, one is created. The source document * is set into state {@link SourceDocumentState#ANNOTATION_IN_PROGRESS}. * * @param document * the source document. * @param user * the user. * @return the JCas. * @throws IOException * if there was an I/O error. * @deprecated use {@link #createOrGetAnnotationDocument(SourceDocument, User)} and * {@link #readAnnotationCas(AnnotationDocument)} instead and manually set source * document status manually if desired. */ @Deprecated JCas readAnnotationCas(SourceDocument document, User user) throws IOException; boolean existsInitialCas(SourceDocument aDocument) throws IOException; JCas createInitialCas(SourceDocument aDocument) throws UIMAException, IOException, ClassNotFoundException; JCas readInitialCas(SourceDocument aDocument) throws CASException, ResourceInitializationException, IOException; JCas createOrReadInitialCas(SourceDocument aDocument) throws IOException, UIMAException, ClassNotFoundException; /** * List all the {@link AnnotationDocument}s, if available for a given {@link SourceDocument} in * the {@link Project}. Returns list of {@link AnnotationDocument}s for all {@link User}s in the * {@link Project} that has already annotated the {@link SourceDocument} * * @param document * the {@link SourceDocument} * @return {@link AnnotationDocument} */ List<AnnotationDocument> listAnnotationDocuments(SourceDocument document); List<AnnotationDocument> listAnnotationDocuments(Project project, User user); /** * Number of expected annotation documents in this project (numUser X document - Ignored) * * @param project * the project. * @return the number of annotation documents. */ int numberOfExpectedAnnotationDocuments(Project project); /** * List all annotation Documents in a project that are already closed. used to compute overall * project progress * * @param project * the project. * @return the annotation documents. */ List<AnnotationDocument> listFinishedAnnotationDocuments(Project project); /** * List all annotation documents for this source document (including in active and delted user * annotation and those created by project admins or super admins for Test purpose. This method * is called when a source document (or Project) is deleted so that associated annotation * documents also get removed. * * @param document * the source document. * @return the annotation documents. */ List<AnnotationDocument> listAllAnnotationDocuments(SourceDocument document); /** * Check if the user finished annotating the {@link SourceDocument} in this {@link Project} * * @param document * the source document. * @param user * the user. * @return if the user has finished annotation. */ boolean isAnnotationFinished(SourceDocument document, User user); /** * Check if at least one annotation document is finished for this {@link SourceDocument} in the * project * * @param document * the source document. * @return if any finished annotation exists. */ boolean existsFinishedAnnotation(SourceDocument document); /** * If at least one {@link AnnotationDocument} is finished in this project */ boolean existsFinishedAnnotation(Project project); /** * Remove an annotation document, for example, when a user is removed from a project * * @param annotationDocument * the {@link AnnotationDocument} to be removed */ void removeAnnotationDocument(AnnotationDocument annotationDocument); void upgradeCas(CAS aCurCas, AnnotationDocument annotationDocument) throws UIMAException, IOException; /** * If any of the users finished one annotation document */ boolean existFinishedDocument(SourceDocument aSourceDocument, Project aProject); AnnotationDocument createOrGetAnnotationDocument(SourceDocument aDocument, User aUser); /** * Returns the annotatable {@link SourceDocument source documents} from the given project for * the given user. Annotatable documents are those for which there is no corresponding * {@link AnnotationDocument annotation document} with the state * {@link AnnotationDocumentState#IGNORE}. Mind that annotation documents are created lazily * in the database, thus there may be source documents without associated annotation documents. * In order to provide access to the status of a document for a given user, the results is * returned as a map where the source document is the key and the annotation document is the * value. The annotation document may be {@code null}. */ Map<SourceDocument, AnnotationDocument> listAnnotatableDocuments(Project aProject, User aUser); }