From 59c74e21bb5e125e6d3b06329237d8c80d3d230e Mon Sep 17 00:00:00 2001 From: GordeaS Date: Mon, 17 Jun 2024 16:32:22 +0200 Subject: [PATCH 1/2] add maven project info reports plugin --- annotation-tests/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/annotation-tests/pom.xml b/annotation-tests/pom.xml index 9b99786c..2817131b 100644 --- a/annotation-tests/pom.xml +++ b/annotation-tests/pom.xml @@ -162,4 +162,11 @@ + + + + maven-project-info-reports-plugin + + + From 82ec04ecee14f7ce88ff97807d6a68acae12312f Mon Sep 17 00:00:00 2001 From: GordeaS Date: Mon, 17 Jun 2024 16:48:55 +0200 Subject: [PATCH 2/2] code formatting, removed commented out code --- annotation-tests/pom.xml | 7 - annotation-web/pom.xml | 7 + .../controller/jsonld/BaseJsonldRest.java | 1217 +++++++++-------- .../jsonld/WebAnnotationProtocolRest.java | 5 +- .../service/impl/AnnotationServiceImpl.java | 3 +- 5 files changed, 636 insertions(+), 603 deletions(-) diff --git a/annotation-tests/pom.xml b/annotation-tests/pom.xml index 2817131b..9b99786c 100644 --- a/annotation-tests/pom.xml +++ b/annotation-tests/pom.xml @@ -162,11 +162,4 @@ - - - - maven-project-info-reports-plugin - - - diff --git a/annotation-web/pom.xml b/annotation-web/pom.xml index 795632ef..d2400e95 100644 --- a/annotation-web/pom.xml +++ b/annotation-web/pom.xml @@ -287,4 +287,11 @@ + + + + maven-project-info-reports-plugin + + + diff --git a/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/BaseJsonldRest.java b/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/BaseJsonldRest.java index 2511bd21..d3e23312 100644 --- a/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/BaseJsonldRest.java +++ b/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/BaseJsonldRest.java @@ -64,619 +64,656 @@ public class BaseJsonldRest extends BaseRest { - protected ResponseEntity storeAnnotation(MotivationTypes motivation, boolean indexOnCreate, - String annotation, Authentication authentication) throws HttpException { - - Annotation webAnnotation = null; - try { - // parse - webAnnotation = getAnnotationService().parseAnnotationLd(motivation, annotation); - - // validate annotation and check that no generator and creator exists in input - // set generator and creator - String userId = authentication.getPrincipal().toString(); - String clientId = ((EuropeanaApiCredentials) authentication.getCredentials()).getClientId(); - - String generatorId = AnnotationIdHelper.buildGeneratorUri(getConfiguration().getAnnoClientApiEndpoint(), clientId); - String creatorId = AnnotationIdHelper.buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), userId); - - //overwrite creator and generator with values generated from the JWT token - webAnnotation.setGenerator(buildAgent(generatorId, AgentTypes.SOFTWARE)); - webAnnotation.setCreator(buildAgent(creatorId, AgentTypes.PERSON)); - - // 2. validate - // annotation id cannot be provided in the input of the create method - if (!(webAnnotation.getIdentifier()==0)) - throw new ParamValidationI18NException(ParamValidationI18NException.MESSAGE_ANNOTATION_IDENTIFIER_PROVIDED_UPON_CREATION, - I18nConstantsAnnotation.ANNOTATION_VALIDATION, - new String[] { "identifier", String.valueOf(webAnnotation.getIdentifier()) }); - // 2.1 validate annotation properties - getAnnotationService().validateWebAnnotation(webAnnotation, authentication); - - //check the annotation uniqueness, only after validation - Set duplicateAnnotationIds = getAnnotationService().checkDuplicateAnnotations(webAnnotation, false); - if(!duplicateAnnotationIds.isEmpty()) { - String [] i18nParamsAnnoDuplicates = new String [1]; - i18nParamsAnnoDuplicates[0]=String.join(",", duplicateAnnotationIds); - throw new AnnotationUniquenessValidationException(I18nConstantsAnnotation.ANNOTATION_DUPLICATION, - I18nConstantsAnnotation.ANNOTATION_DUPLICATION, i18nParamsAnnoDuplicates); - } - - // 3-6 create ID and annotation + backend validation - long annoIdentifier = mongoPersistance.generateAnnotationIdentifier(); - webAnnotation.setIdentifier(annoIdentifier); - - // validate api key ... and request limit only if the request is - // correct (avoid useless DB requests) - // Done in authorize user - // validateApiKey(wsKey); - - Annotation storedAnnotation = getAnnotationService().storeAnnotation(webAnnotation, indexOnCreate); - - // serialize to jsonld - JsonLd annotationLd = new AnnotationLdSerializer(storedAnnotation, getConfiguration().getAnnotationBaseUrl()); - String jsonLd = annotationLd.toString(4); - - // build response entity with headers - // TODO: clarify serialization ETag: "_87e52ce126126" - // TODO: clarify Allow: PUT,GET,DELETE,OPTIONS,HEAD,PATCH -// String apiVersion = getConfiguration().getAnnotationApiVersion(); - String eTag = generateETag(storedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.ETAG, eTag); - headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); - headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_POST); - - ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.CREATED); - - return response; - - } catch (JsonParseException e) { - throw new RequestBodyValidationException(annotation, I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); - } catch (AnnotationValidationException e) { // TODO: transform to - // checked annotation type - throw new RequestBodyValidationException(annotation, I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); - } catch (AnnotationAttributeInstantiationException e) { - throw new RequestBodyValidationException(annotation, I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); - } catch (AnnotationInstantiationException e) { - throw new HttpException(null, I18nConstantsAnnotation.ANNOTATION_INVALID_BODY, null, HttpStatus.BAD_REQUEST, e); - } catch (HttpException e) { - // avoid wrapping HttpExceptions - throw e; - } catch (AnnotationServiceException e) { - String debugInfo = (webAnnotation != null) ? webAnnotation.toString() : ""; - throw SearchServiceUtils.convertSolrSearchException(debugInfo, e); - } catch (Exception e) { - throw new InternalServerException(e); - } - - } - - /** - * - * @param wsKey - * @param annotationPageIn - * @param authentication - * @return - * @throws HttpException - */ - protected ResponseEntity storeAnnotations(String annotationPageIn, Authentication authentication) - throws HttpException { - try { - - String userId = authentication.getPrincipal().toString(); - - // parse annotation page - AnnotationPageParser annoPageParser = new AnnotationPageParser(); - AnnotationPage annotationPage = annoPageParser.parseAnnotationPage(annotationPageIn); - List annotations = annotationPage.getAnnotations(); - - // initialize upload status - BatchUploadStatus uploadStatus = new BatchUploadStatus(); - uploadStatus.setTotalNumberOfAnnotations(annotations.size()); - - // validate annotations - uploadStatus.setStep(BatchOperationStep.VALIDATION); - getAnnotationService().validateWebAnnotations(annotations, uploadStatus, authentication); - - // in case of validation errors, return error report - if (uploadStatus.getFailureCount() > 0) - throw new BatchUploadException(uploadStatus.toString(), uploadStatus); - - AnnotationsList webAnnotations = new AnnotationsList(annotationPage.getAnnotations()); - - // annotations are separated into those with identifier (assumed updates) - // and those without identifier (new annotations which should be created); - // first annotations with identifier (assumed updates) - AnnotationsList annosWithId = webAnnotations.getAnnotationsWithId(); - uploadStatus.setNumberOfAnnotationsWithId(annosWithId.size()); - - // verify if the annotations with identifiers exist in the database - List annoIdentifiers = annosWithId.getIdentifiers(); - AnnotationsList existingInDb; - - if (!annoIdentifiers.isEmpty()) { - existingInDb = new AnnotationsList(getAnnotationService().getExisting(annoIdentifiers)); - } - else { - existingInDb = new AnnotationsList(new ArrayList(0)); - } - - // consistency (annotations with identifier must match existing annotations) - uploadStatus.setStep(BatchOperationStep.CHECK_UPDATE_ANNOTATIONS_AVAILABLE); - if (annosWithId.size() != existingInDb.size()) { - // remove existing identifiers, the remaining list contains only missing identifiers - annoIdentifiers.removeAll(existingInDb.getIdentifiers()); - getAnnotationService().reportNonExisting(annotations, uploadStatus, annoIdentifiers); - throw new BatchUploadException(uploadStatus.toString(), uploadStatus, HttpStatus.NOT_FOUND); - } - - LinkedHashMap webAnnoStoredAnnoAnnoMap = webAnnotations.getAnnotationsMap(); - - // update existing annotations - if (annosWithId.getAnnotations().size() > 0) { - uploadStatus.setStep(BatchOperationStep.UPDATE_EXISTING_ANNOTATIONS); - getAnnotationService().updateExistingAnnotations(uploadStatus, existingInDb.getAnnotations(), - annosWithId.getAnnotations(), webAnnoStoredAnnoAnnoMap); - } - // annotations are separated into those with identifier (assumed updates) - // and those without identifier (new annotations which should be created); - // second annotations without (assumed inserts) - AnnotationsList annosWithoutId = webAnnotations.getAnnotationsWithoutId(); - uploadStatus.setStep(BatchOperationStep.INSERT_NEW_ANNOTATIONS); - uploadStatus.setNumberOfAnnotationsWithoutId(annosWithoutId.size()); - // default values - if (annosWithoutId.size() > 0) { - String clientId = ((EuropeanaApiCredentials) authentication.getCredentials()).getClientId(); - String generatorId = AnnotationIdHelper.buildGeneratorUri(getConfiguration().getAnnoClientApiEndpoint(), clientId); - String creatorId = AnnotationIdHelper.buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), userId); - - // getAuthorizationService().authorizeUser(userId,authentication, Operations.CREATE); - AnnotationDefaults annoDefaults = new AnnotationDefaults.Builder().setGenerator(buildAgent(generatorId, AgentTypes.SOFTWARE)) - .setUser(buildAgent(creatorId, AgentTypes.PERSON)).build(); - getAnnotationService().insertNewAnnotations(uploadStatus, annosWithoutId.getAnnotations(), annoDefaults, - webAnnoStoredAnnoAnnoMap); - } - - // create result annotation page - AnnotationPage apRes = new AnnotationPageImpl(); - List resList = new ArrayList(); - // the "web annotation - stored annotation" map has preserved the order of - // submitted annotations - for (Annotation ann : webAnnoStoredAnnoAnnoMap.keySet()) - resList.add(webAnnoStoredAnnoAnnoMap.get(ann)); - apRes.setAnnotations(resList); - apRes.setTotalInCollection(resList.size()); - apRes.setTotalInPage(resList.size()); -// apRes.setCurrentPageUri("http://UNDEFINED"); - - String jsonLd = (new AnnotationPageSerializer(apRes, getConfiguration().getAnnotationBaseUrl())).serialize(SearchProfiles.STANDARD); - - MultiValueMap headers = new LinkedMultiValueMap(3); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); - headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_POST); - - // build response - ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.CREATED); - - return response; - - } catch (AnnotationInstantiationException e) { - throw new HttpException("The submitted annotation body is invalid!", I18nConstantsAnnotation.ANNOTATION_INVALID_BODY, - null, HttpStatus.BAD_REQUEST, e); - } catch (HttpException e) { - // avoid wrapping HttpExceptions - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } - + protected ResponseEntity storeAnnotation(MotivationTypes motivation, + boolean indexOnCreate, String annotation, Authentication authentication) + throws HttpException { + + Annotation webAnnotation = null; + try { + // parse + webAnnotation = getAnnotationService().parseAnnotationLd(motivation, annotation); + + // validate annotation and check that no generator and creator exists in input + // set generator and creator + String userId = authentication.getPrincipal().toString(); + String clientId = ((EuropeanaApiCredentials) authentication.getCredentials()).getClientId(); + + String generatorId = AnnotationIdHelper + .buildGeneratorUri(getConfiguration().getAnnoClientApiEndpoint(), clientId); + String creatorId = + AnnotationIdHelper.buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), userId); + + // overwrite creator and generator with values generated from the JWT token + webAnnotation.setGenerator(buildAgent(generatorId, AgentTypes.SOFTWARE)); + webAnnotation.setCreator(buildAgent(creatorId, AgentTypes.PERSON)); + + // 2. validate + // annotation id cannot be provided in the input of the create method + if (!(webAnnotation.getIdentifier() == 0)) + throw new ParamValidationI18NException( + ParamValidationI18NException.MESSAGE_ANNOTATION_IDENTIFIER_PROVIDED_UPON_CREATION, + I18nConstantsAnnotation.ANNOTATION_VALIDATION, + new String[] {"identifier", String.valueOf(webAnnotation.getIdentifier())}); + // 2.1 validate annotation properties + getAnnotationService().validateWebAnnotation(webAnnotation, authentication); + + // check the annotation uniqueness, only after validation + Set duplicateAnnotationIds = + getAnnotationService().checkDuplicateAnnotations(webAnnotation, false); + if (!duplicateAnnotationIds.isEmpty()) { + String[] i18nParamsAnnoDuplicates = new String[1]; + i18nParamsAnnoDuplicates[0] = String.join(",", duplicateAnnotationIds); + throw new AnnotationUniquenessValidationException( + I18nConstantsAnnotation.ANNOTATION_DUPLICATION, + I18nConstantsAnnotation.ANNOTATION_DUPLICATION, i18nParamsAnnoDuplicates); + } + + // 3-6 create ID and annotation + backend validation + long annoIdentifier = mongoPersistance.generateAnnotationIdentifier(); + webAnnotation.setIdentifier(annoIdentifier); + + Annotation storedAnnotation = + getAnnotationService().storeAnnotation(webAnnotation, indexOnCreate); + + // serialize to jsonld + JsonLd annotationLd = + new AnnotationLdSerializer(storedAnnotation, getConfiguration().getAnnotationBaseUrl()); + String jsonLd = annotationLd.toString(4); + + // build response entity with headers + // TODO: clarify serialization ETag: "_87e52ce126126" + String eTag = generateETag(storedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, + buildInfo.getVersion()); + + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.ETAG, eTag); + headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); + headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_POST); + + ResponseEntity response = + new ResponseEntity(jsonLd, headers, HttpStatus.CREATED); + + return response; + + } catch (JsonParseException e) { + throw new RequestBodyValidationException(annotation, + I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); + } catch (AnnotationValidationException e) { + // TODO: transform to checked annotation type + throw new RequestBodyValidationException(annotation, + I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); + } catch (AnnotationAttributeInstantiationException e) { + throw new RequestBodyValidationException(annotation, + I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); + } catch (AnnotationInstantiationException e) { + throw new HttpException(null, I18nConstantsAnnotation.ANNOTATION_INVALID_BODY, null, + HttpStatus.BAD_REQUEST, e); + } catch (HttpException e) { + // avoid wrapping HttpExceptions + throw e; + } catch (AnnotationServiceException e) { + String debugInfo = (webAnnotation != null) ? webAnnotation.toString() : ""; + throw SearchServiceUtils.convertSolrSearchException(debugInfo, e); + } catch (Exception e) { + throw new InternalServerException(e); } - /** - * This method builds agent object - * - * @param id agent id - * @return agent as an Agent object - */ - protected Agent buildAgent(String id, AgentTypes type) { - Agent agent = AgentObjectFactory.getInstance().createObjectInstance(type); - agent.setHttpUrl(id); -// agent.setName(id); - return agent; + } + + /** + * + * @param wsKey + * @param annotationPageIn + * @param authentication + * @return + * @throws HttpException + */ + protected ResponseEntity storeAnnotations(String annotationPageIn, + Authentication authentication) throws HttpException { + try { + + String userId = authentication.getPrincipal().toString(); + + // parse annotation page + AnnotationPageParser annoPageParser = new AnnotationPageParser(); + AnnotationPage annotationPage = annoPageParser.parseAnnotationPage(annotationPageIn); + List annotations = annotationPage.getAnnotations(); + + // initialize upload status + BatchUploadStatus uploadStatus = new BatchUploadStatus(); + uploadStatus.setTotalNumberOfAnnotations(annotations.size()); + + // validate annotations + uploadStatus.setStep(BatchOperationStep.VALIDATION); + getAnnotationService().validateWebAnnotations(annotations, uploadStatus, authentication); + + // in case of validation errors, return error report + if (uploadStatus.getFailureCount() > 0) + throw new BatchUploadException(uploadStatus.toString(), uploadStatus); + + AnnotationsList webAnnotations = new AnnotationsList(annotationPage.getAnnotations()); + + // annotations are separated into those with identifier (assumed updates) + // and those without identifier (new annotations which should be created); + // first annotations with identifier (assumed updates) + AnnotationsList annosWithId = webAnnotations.getAnnotationsWithId(); + uploadStatus.setNumberOfAnnotationsWithId(annosWithId.size()); + + // verify if the annotations with identifiers exist in the database + List annoIdentifiers = annosWithId.getIdentifiers(); + AnnotationsList existingInDb; + + if (!annoIdentifiers.isEmpty()) { + existingInDb = new AnnotationsList(getAnnotationService().getExisting(annoIdentifiers)); + } else { + existingInDb = new AnnotationsList(new ArrayList(0)); + } + + // consistency (annotations with identifier must match existing annotations) + uploadStatus.setStep(BatchOperationStep.CHECK_UPDATE_ANNOTATIONS_AVAILABLE); + if (annosWithId.size() != existingInDb.size()) { + // remove existing identifiers, the remaining list contains only missing identifiers + annoIdentifiers.removeAll(existingInDb.getIdentifiers()); + getAnnotationService().reportNonExisting(annotations, uploadStatus, annoIdentifiers); + throw new BatchUploadException(uploadStatus.toString(), uploadStatus, HttpStatus.NOT_FOUND); + } + + LinkedHashMap webAnnoStoredAnnoAnnoMap = + webAnnotations.getAnnotationsMap(); + + // update existing annotations + if (annosWithId.getAnnotations().size() > 0) { + uploadStatus.setStep(BatchOperationStep.UPDATE_EXISTING_ANNOTATIONS); + getAnnotationService().updateExistingAnnotations(uploadStatus, + existingInDb.getAnnotations(), annosWithId.getAnnotations(), webAnnoStoredAnnoAnnoMap); + } + // annotations are separated into those with identifier (assumed updates) + // and those without identifier (new annotations which should be created); + // second annotations without (assumed inserts) + AnnotationsList annosWithoutId = webAnnotations.getAnnotationsWithoutId(); + uploadStatus.setStep(BatchOperationStep.INSERT_NEW_ANNOTATIONS); + uploadStatus.setNumberOfAnnotationsWithoutId(annosWithoutId.size()); + // default values + if (annosWithoutId.size() > 0) { + String clientId = ((EuropeanaApiCredentials) authentication.getCredentials()).getClientId(); + String generatorId = AnnotationIdHelper + .buildGeneratorUri(getConfiguration().getAnnoClientApiEndpoint(), clientId); + String creatorId = AnnotationIdHelper + .buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), userId); + + // getAuthorizationService().authorizeUser(userId,authentication, Operations.CREATE); + AnnotationDefaults annoDefaults = new AnnotationDefaults.Builder() + .setGenerator(buildAgent(generatorId, AgentTypes.SOFTWARE)) + .setUser(buildAgent(creatorId, AgentTypes.PERSON)).build(); + getAnnotationService().insertNewAnnotations(uploadStatus, annosWithoutId.getAnnotations(), + annoDefaults, webAnnoStoredAnnoAnnoMap); + } + + // create result annotation page + AnnotationPage apRes = new AnnotationPageImpl(); + List resList = new ArrayList(); + // the "web annotation - stored annotation" map has preserved the order of + // submitted annotations + for (Annotation ann : webAnnoStoredAnnoAnnoMap.keySet()) + resList.add(webAnnoStoredAnnoAnnoMap.get(ann)); + apRes.setAnnotations(resList); + apRes.setTotalInCollection(resList.size()); + apRes.setTotalInPage(resList.size()); + // apRes.setCurrentPageUri("http://UNDEFINED"); + + String jsonLd = + (new AnnotationPageSerializer(apRes, getConfiguration().getAnnotationBaseUrl())) + .serialize(SearchProfiles.STANDARD); + + MultiValueMap headers = new LinkedMultiValueMap(3); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); + headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_POST); + + // build response + ResponseEntity response = + new ResponseEntity(jsonLd, headers, HttpStatus.CREATED); + + return response; + + } catch (AnnotationInstantiationException e) { + throw new HttpException("The submitted annotation body is invalid!", + I18nConstantsAnnotation.ANNOTATION_INVALID_BODY, null, HttpStatus.BAD_REQUEST, e); + } catch (HttpException e) { + // avoid wrapping HttpExceptions + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } - /** - * This method retrieves annotation by ID optionally providing profile and - * language - * - * @param identifier - * @param profileStr e.g. "dereference" - * @param language e.g. - * "en,pl,de,nl,fr,it,da,sv,el,fi,hu,cs,sl,et,pt,es,lt,lv,bg,ro,sk,hr,ga,mt,no,ca,ru" - * @return - * @throws HttpException - */ - protected ResponseEntity getAnnotationById(long identifier, String profileStr, String language) - throws HttpException { - - try { - - // 4. If annotation doesn’t exist respond with HTTP 404 (if provided - // annotation id doesn’t exists ) - // 4.or 410 (if the user is not allowed to access the annotation); - Annotation annotation = getAnnotationService().getAnnotationById(identifier, null, true); - - SearchProfiles searchProfile = SearchProfiles.getByStr(profileStr); - // will update body if dereference profile is used - getAnnotationService().dereferenceSemanticTags(annotation, searchProfile, language); - - JsonLd annotationLd = new AnnotationLdSerializer(annotation, getConfiguration().getAnnotationBaseUrl()); - String jsonLd = annotationLd.toString(4); - -// String apiVersion = getConfiguration().getAnnotationApiVersion(); - String eTag = generateETag(annotation.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.ETAG, eTag); - headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); - headers.add(HttpHeaders.ALLOW, AnnotationHttpHeaders.ALLOW_GPuDOH); - - ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); - - return response; - - } catch (UpstreamServerErrorRuntimeException e) { - throw new UpstreamServerErrorHttpException(I18nConstantsAnnotation.UPSTREAM_SERVER_ACCESS, - I18nConstantsAnnotation.UPSTREAM_SERVER_ACCESS, null, e); - } catch (RuntimeException e) { - // not found .. - throw new InternalServerException(e); - } catch (HttpException e) { - // avoid wrapping http exception - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } + } + + /** + * This method builds agent object + * + * @param id agent id + * @return agent as an Agent object + */ + protected Agent buildAgent(String id, AgentTypes type) { + Agent agent = AgentObjectFactory.getInstance().createObjectInstance(type); + agent.setHttpUrl(id); + // agent.setName(id); + return agent; + } + + /** + * This method retrieves annotation by ID optionally providing profile and language + * + * @param identifier + * @param profileStr e.g. "dereference" + * @param language e.g. + * "en,pl,de,nl,fr,it,da,sv,el,fi,hu,cs,sl,et,pt,es,lt,lv,bg,ro,sk,hr,ga,mt,no,ca,ru" + * @return + * @throws HttpException + */ + protected ResponseEntity getAnnotationById(long identifier, String profileStr, + String language) throws HttpException { + + try { + + // 4. If annotation doesn’t exist respond with HTTP 404 (if provided + // annotation id doesn’t exists ) + // 4.or 410 (if the user is not allowed to access the annotation); + Annotation annotation = getAnnotationService().getAnnotationById(identifier, null, true); + + SearchProfiles searchProfile = SearchProfiles.getByStr(profileStr); + // will update body if dereference profile is used + getAnnotationService().dereferenceSemanticTags(annotation, searchProfile, language); + + JsonLd annotationLd = + new AnnotationLdSerializer(annotation, getConfiguration().getAnnotationBaseUrl()); + String jsonLd = annotationLd.toString(4); + + // String apiVersion = getConfiguration().getAnnotationApiVersion(); + String eTag = + generateETag(annotation.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); + + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.ETAG, eTag); + headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); + headers.add(HttpHeaders.ALLOW, AnnotationHttpHeaders.ALLOW_GPuDOH); + + ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); + + return response; + + } catch (UpstreamServerErrorRuntimeException e) { + throw new UpstreamServerErrorHttpException(I18nConstantsAnnotation.UPSTREAM_SERVER_ACCESS, + I18nConstantsAnnotation.UPSTREAM_SERVER_ACCESS, null, e); + } catch (RuntimeException e) { + // not found .. + throw new InternalServerException(e); + } catch (HttpException e) { + // avoid wrapping http exception + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } + } - protected ResponseEntity getModerationReportSummary(String wsKey, long identifier) throws HttpException { + protected ResponseEntity getModerationReportSummary(String wsKey, long identifier) + throws HttpException { - try { + try { - // 2. Check client access (a valid “wskey” must be provided) -// validateApiKey(wsKey, WebAnnotationFields.READ_METHOD); + // 2. Check client access (a valid “wskey” must be provided) + // validateApiKey(wsKey, WebAnnotationFields.READ_METHOD); - // 4. If annotation doesn’t exist respond with HTTP 404 (if provided - // moderation id doesn’t exists ) - ModerationRecord moderationRecord = getAnnotationService().findModerationRecordById(identifier); - if (moderationRecord == null) - moderationRecord = buildNewModerationRecord(identifier, null); + // 4. If annotation doesn’t exist respond with HTTP 404 (if provided + // moderation id doesn’t exists ) + ModerationRecord moderationRecord = + getAnnotationService().findModerationRecordById(identifier); + if (moderationRecord == null) + moderationRecord = buildNewModerationRecord(identifier, null); - Gson gsonObj = new Gson(); - String jsonString = gsonObj.toJson(moderationRecord.getSummary()); + Gson gsonObj = new Gson(); + String jsonString = gsonObj.toJson(moderationRecord.getSummary()); - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.ETAG, Integer.toString(hashCode())); - // headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); - headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_GET); + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.ETAG, Integer.toString(hashCode())); + // headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); + headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_GET); - // build response - ResponseEntity response = new ResponseEntity(jsonString, headers, HttpStatus.OK); + // build response + ResponseEntity response = + new ResponseEntity(jsonString, headers, HttpStatus.OK); - return response; + return response; - } catch (RuntimeException e) { - // not found .. - throw new InternalServerException(e); - } catch (HttpException e) { - // avoid wrapping http exception - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } + } catch (RuntimeException e) { + // not found .. + throw new InternalServerException(e); + } catch (HttpException e) { + // avoid wrapping http exception + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } - - /** - * This method validates input values wsKey, identifier and userToken. - * - * @param identifier - * @param userId - * @param enabled - * @return - * @return annotation object - * @throws HttpException - */ - private Annotation verifyOwnerOrAdmin(long identifier, Authentication authentication, boolean enabled) throws HttpException { - - String userId = AnnotationIdHelper.buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), (String)authentication.getPrincipal()); - Annotation annotation = getAnnotationService().getAnnotationById(identifier, userId, enabled); - - //verify ownership - boolean isOwner = annotation.getCreator().getHttpUrl().equals(userId); - if(isOwner || AnnotationAuthorizationUtils.hasRole(authentication, UserRoles.admin.getName())) { - //approve owner or admin - return annotation; - }else { - //not authorized - //not authorized - throw new ApplicationAuthenticationException(I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, - I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, new String[] { "Only the creators of the annotation or admins are authorized to perform this operation."}, - HttpStatus.FORBIDDEN); - } + } + + /** + * This method validates input values wsKey, identifier and userToken. + * + * @param identifier + * @param userId + * @param enabled + * @return + * @return annotation object + * @throws HttpException + */ + private Annotation verifyOwnerOrAdmin(long identifier, Authentication authentication, + boolean enabled) throws HttpException { + + String userId = AnnotationIdHelper.buildCreatorUri(getConfiguration().getAnnoUserDataEndpoint(), + (String) authentication.getPrincipal()); + Annotation annotation = getAnnotationService().getAnnotationById(identifier, userId, enabled); + + // verify ownership + boolean isOwner = annotation.getCreator().getHttpUrl().equals(userId); + if (isOwner + || AnnotationAuthorizationUtils.hasRole(authentication, UserRoles.admin.getName())) { + // approve owner or admin + return annotation; + } else { + // not authorized + // not authorized + throw new ApplicationAuthenticationException(I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, + I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, + new String[] { + "Only the creators of the annotation or admins are authorized to perform this operation."}, + HttpStatus.FORBIDDEN); } - - /** - * This method validates input values, retrieves annotation object and updates - * it. - * - * @param identifier - * @param annotation - * @param authentication Contains user name - * @param action - * @return response entity that comprises response body, headers and status code - * @throws HttpException - */ - protected ResponseEntity updateAnnotation(long identifier, String annotation, - Authentication authentication, HttpServletRequest request) throws HttpException { - - try { -// String userId = authentication.getPrincipal().toString(); - - // 1. authorize user - // already performed in verify write access - // getAuthorizationService().authorizeUser(userId, authentication, annoId, - // Operations.UPDATE); - // check permissions for update - Annotation storedAnnotation = verifyOwnerOrAdmin(identifier, authentication, true); - - // 2. check time stamp - // 3. validate new description for format and fields - // 4. generate new and replace existing time stamp for annotation - - // Retrieve an annotation based on its identifier; -// PersistentAnnotation storedAnnotation = getAnnotationForUpdate(getConfiguration().getAnnotationBaseUrl(), provider, -// identifier); - - // TODO: #431 update specification steps performed here - // 5. parse updated annotation - Annotation updateWebAnnotation = getAnnotationService().parseAnnotationLd(null, annotation); - - // validate annotation -// String apiVersion = getConfiguration().getAnnotationApiVersion(); - String eTagOrigin = generateETag(storedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - - checkIfMatchHeader(eTagOrigin, request); - getAnnotationService().validateWebAnnotation(updateWebAnnotation, authentication); - - // 6. apply updates - merge current and updated annotation - // 7. and call database update method - Annotation updatedAnnotation = getAnnotationService() - .updateAnnotation((PersistentAnnotation) storedAnnotation, updateWebAnnotation); - - String eTag = generateETag(updatedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - - // serialize to jsonld - JsonLd annotationLd = new AnnotationLdSerializer(updatedAnnotation, getConfiguration().getAnnotationBaseUrl()); - String jsonLd = annotationLd.toString(4); - - // build response entity with headers - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.ETAG, eTag); - headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); - headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_GPuD); - - ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); - - return response; - - } catch (JsonParseException e) { - throw new RequestBodyValidationException(annotation, I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); - } catch (AnnotationValidationException e) { - throw new RequestBodyValidationException(annotation, I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); - } catch (HttpException e) { - throw e; - } catch (AnnotationInstantiationException e) { - throw new HttpException("The submitted annotation body is invalid!", I18nConstantsAnnotation.ANNOTATION_VALIDATION, - null, HttpStatus.BAD_REQUEST, e); - } catch (AnnotationServiceException e) { + } + + /** + * This method validates input values, retrieves annotation object and updates it. + * + * @param identifier + * @param annotation + * @param authentication Contains user name + * @param action + * @return response entity that comprises response body, headers and status code + * @throws HttpException + */ + protected ResponseEntity updateAnnotation(long identifier, String annotation, + Authentication authentication, HttpServletRequest request) throws HttpException { + + try { + // String userId = authentication.getPrincipal().toString(); + + // 1. authorize user + // already performed in verify write access + // getAuthorizationService().authorizeUser(userId, authentication, annoId, + // Operations.UPDATE); + // check permissions for update + Annotation storedAnnotation = verifyOwnerOrAdmin(identifier, authentication, true); + + // 2. check time stamp + // 3. validate new description for format and fields + // 4. generate new and replace existing time stamp for annotation + + // Retrieve an annotation based on its identifier; + // PersistentAnnotation storedAnnotation = + // getAnnotationForUpdate(getConfiguration().getAnnotationBaseUrl(), provider, + // identifier); + + // TODO: #431 update specification steps performed here + // 5. parse updated annotation + Annotation updateWebAnnotation = getAnnotationService().parseAnnotationLd(null, annotation); + + // validate annotation + // String apiVersion = getConfiguration().getAnnotationApiVersion(); + String eTagOrigin = generateETag(storedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, + buildInfo.getVersion()); + + checkIfMatchHeader(eTagOrigin, request); + getAnnotationService().validateWebAnnotation(updateWebAnnotation, authentication); + + // 6. apply updates - merge current and updated annotation + // 7. and call database update method + Annotation updatedAnnotation = getAnnotationService() + .updateAnnotation((PersistentAnnotation) storedAnnotation, updateWebAnnotation); + + String eTag = generateETag(updatedAnnotation.getGenerated(), WebFields.FORMAT_JSONLD, + buildInfo.getVersion()); + + // serialize to jsonld + JsonLd annotationLd = + new AnnotationLdSerializer(updatedAnnotation, getConfiguration().getAnnotationBaseUrl()); + String jsonLd = annotationLd.toString(4); + + // build response entity with headers + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.ETAG, eTag); + headers.add(HttpHeaders.LINK, HttpHeaders.VALUE_LDP_RESOURCE); + headers.add(HttpHeaders.ALLOW, HttpHeaders.ALLOW_GPuD); + + ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); + + return response; + + } catch (JsonParseException e) { + throw new RequestBodyValidationException(annotation, + I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); + } catch (AnnotationValidationException e) { + throw new RequestBodyValidationException(annotation, + I18nConstantsAnnotation.ANNOTATION_CANT_PARSE_BODY, e); + } catch (HttpException e) { + throw e; + } catch (AnnotationInstantiationException e) { + throw new HttpException("The submitted annotation body is invalid!", + I18nConstantsAnnotation.ANNOTATION_VALIDATION, null, HttpStatus.BAD_REQUEST, e); + } catch (AnnotationServiceException e) { throw SearchServiceUtils.convertSolrSearchException(annotation, e); } catch (Exception e) { throw new InternalServerException(e); } + } + + /** + * This method validates input values, retrieves annotation object and deletes it. + * + * @param wsKey + * @param identifier + * @param authentication Contains user name + * @param action + * @return response entity that comprises response body, headers and status code + * @throws HttpException + */ + protected ResponseEntity deleteAnnotation(long identifier, Authentication authentication, + HttpServletRequest request) throws HttpException { + + try { + // String userId = authentication.getPrincipal().toString(); + + // 5. authorize user + // already performed in verify write access + // getAuthorizationService().authorizeUser(userId, authentication, annoId, Operations.DELETE); + + // Retrieve an annotation based on its id; + // Verify if user is allowed to perform the deletion. + Annotation storedAnno = verifyOwnerOrAdmin(identifier, authentication, true); + + // validate annotation + // String apiVersion = getConfiguration().getAnnotationApiVersion(); + String eTagOrigin = + generateETag(storedAnno.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); + + checkIfMatchHeader(eTagOrigin, request); + + // call database delete method that deactivates existing Annotation + // in Mongo + getAnnotationService().disableAnnotation(storedAnno); + + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + + ResponseEntity response = + new ResponseEntity(null, headers, HttpStatus.NO_CONTENT); + + return response; + + } catch (HttpException e) { + // avoid wrapping HttpExceptions + // TODO: change this when OAUTH is implemented and the user information is + // available in service + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } - - /** - * This method validates input values, retrieves annotation object and deletes - * it. - * - * @param wsKey - * @param identifier - * @param authentication Contains user name - * @param action - * @return response entity that comprises response body, headers and status code - * @throws HttpException - */ - protected ResponseEntity deleteAnnotation(long identifier, Authentication authentication, HttpServletRequest request) - throws HttpException { - - try { -// String userId = authentication.getPrincipal().toString(); - - // 5. authorize user - // already performed in verify write access -// getAuthorizationService().authorizeUser(userId, authentication, annoId, Operations.DELETE); - - // Retrieve an annotation based on its id; - // Verify if user is allowed to perform the deletion. - Annotation storedAnno = verifyOwnerOrAdmin(identifier, authentication, true); - - // validate annotation - //String apiVersion = getConfiguration().getAnnotationApiVersion(); - String eTagOrigin = generateETag(storedAnno.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - - checkIfMatchHeader(eTagOrigin, request); - - // call database delete method that deactivates existing Annotation - // in Mongo - getAnnotationService().disableAnnotation(storedAnno); - - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - - ResponseEntity response = new ResponseEntity(null, headers, HttpStatus.NO_CONTENT); - - return response; - - } catch (HttpException e) { - // avoid wrapping HttpExceptions - // TODO: change this when OAUTH is implemented and the user information is - // available in service - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } - } - - /** - * This method enables the disabled annotation. It validates the input values, - * updates the annotation object in the database and creates it in solr. - * @param identifier - * @param authentication Contains user name - * @param request An HttpServletRequest - * @return response entity that comprises response body, headers and status code - * @throws HttpException - */ - protected ResponseEntity enableAnnotation(long identifier, Authentication authentication, HttpServletRequest request) - throws HttpException { - - try { - // Retrieve an annotation based on its id. - // Verify if user is allowed to perform the action. - Annotation storedAnno = verifyOwnerOrAdmin(identifier, authentication, false); - - // validate annotation - //String apiVersion = getConfiguration().getAnnotationApiVersion(); - String eTagOrigin = generateETag(storedAnno.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); - checkIfMatchHeader(eTagOrigin, request); - - getAnnotationService().enableAnnotation(storedAnno.getIdentifier()); - - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - - JsonLd annotationLd = new AnnotationLdSerializer(storedAnno, getConfiguration().getAnnotationBaseUrl()); - String jsonLd = annotationLd.toString(4); - - ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); - - return response; - - } catch (HttpException e) { - // avoid wrapping HttpExceptions - // TODO: change this when OAUTH is implemented and the user information is - // available in service - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } - } - - /** - * @param wsKey - * @param provider - * @param identifier - * @param authentication Contains user name - * @return - * @throws HttpException - */ - protected ResponseEntity storeAnnotationReport(long identifier, Authentication authentication) - throws HttpException { - try { - - // 1. authorize user - // already performed in verify write access -// getAuthorizationService().authorizeUser(userId, authentication, annoId, Operations.REPORT); - - // 2. build and verify annotation ID - String userId = authentication.getPrincipal().toString(); - if(!getAnnotationService().existsInDb(identifier)) { - throw new ParamValidationI18NException(ParamValidationI18NException.MESSAGE_ANNOTATION_ID_EXISTS, - I18nConstantsAnnotation.ANNOTATION_VALIDATION, - new String[] { "identifier", String.valueOf(identifier) }); - } - - // build vote - Date reportDate = new Date(); - Vote vote = buildVote(buildAgent(userId, AgentTypes.PERSON), reportDate); - - // 3. Check if the user has already reported this annotation - ModerationRecord moderationRecord = getAnnotationService().findModerationRecordById(identifier); - if (moderationRecord == null) - moderationRecord = buildNewModerationRecord(identifier, reportDate); - else - validateVote(moderationRecord, vote); - - moderationRecord.addReport(vote); - moderationRecord.computeSummary(); - moderationRecord.setLastUpdated(reportDate); - - // update record in the database - ModerationRecord storedModeration = getAnnotationService().storeModerationRecord(moderationRecord); - - // build response - MultiValueMap headers = new LinkedMultiValueMap(5); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - headers.add(HttpHeaders.ETAG, Long.toString(storedModeration.getLastUpdated().hashCode())); - // headers.add(HttpHeaders.LINK, - // "; rel=\"type\""); - headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); - - ResponseEntity response = new ResponseEntity(null, headers, HttpStatus.CREATED); - return response; - - } catch (HttpException e) { - // avoid wrapping HttpExceptions - throw e; - } catch (Exception e) { - throw new InternalServerException(e); - } - } - - // TODO :consider moving to persistent moderation record service - private void validateVote(ModerationRecord moderationRecord, Vote vote) throws OperationAuthorizationException { - for (Vote existingVote : moderationRecord.getReportList()) { - if (vote.getUserId().equals(existingVote.getUserId())) - throw new OperationAuthorizationException("A report from the same users exists in database!", - I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, new String[] { vote.getUserId() }); - } + } + + /** + * This method enables the disabled annotation. It validates the input values, updates the + * annotation object in the database and creates it in solr. + * + * @param identifier + * @param authentication Contains user name + * @param request An HttpServletRequest + * @return response entity that comprises response body, headers and status code + * @throws HttpException + */ + protected ResponseEntity enableAnnotation(long identifier, Authentication authentication, + HttpServletRequest request) throws HttpException { + + try { + // Retrieve an annotation based on its id. + // Verify if user is allowed to perform the action. + Annotation storedAnno = verifyOwnerOrAdmin(identifier, authentication, false); + + // validate annotation + // String apiVersion = getConfiguration().getAnnotationApiVersion(); + String eTagOrigin = + generateETag(storedAnno.getGenerated(), WebFields.FORMAT_JSONLD, buildInfo.getVersion()); + checkIfMatchHeader(eTagOrigin, request); + + getAnnotationService().enableAnnotation(storedAnno.getIdentifier()); + + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + + JsonLd annotationLd = + new AnnotationLdSerializer(storedAnno, getConfiguration().getAnnotationBaseUrl()); + String jsonLd = annotationLd.toString(4); + + ResponseEntity response = new ResponseEntity(jsonLd, headers, HttpStatus.OK); + + return response; + + } catch (HttpException e) { + // avoid wrapping HttpExceptions + // TODO: change this when OAUTH is implemented and the user information is + // available in service + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } - - protected ModerationRecord buildNewModerationRecord(long annoIdentifier, Date reportDate) { - // create moderation record - ModerationRecord moderationRecord = new BaseModerationRecord(); - moderationRecord.setIdentifier(annoIdentifier); - - // SET DEFAULTS - moderationRecord.setCreated(reportDate); - moderationRecord.setLastUpdated(reportDate); - - Summary summary = new BaseSummary(); - moderationRecord.setSummary(summary); - return moderationRecord; + } + + /** + * @param wsKey + * @param provider + * @param identifier + * @param authentication Contains user name + * @return + * @throws HttpException + */ + protected ResponseEntity storeAnnotationReport(long identifier, + Authentication authentication) throws HttpException { + try { + + // 1. authorize user + // already performed in verify write access + // getAuthorizationService().authorizeUser(userId, authentication, annoId, Operations.REPORT); + + // 2. build and verify annotation ID + String userId = authentication.getPrincipal().toString(); + if (!getAnnotationService().existsInDb(identifier)) { + throw new ParamValidationI18NException( + ParamValidationI18NException.MESSAGE_ANNOTATION_ID_EXISTS, + I18nConstantsAnnotation.ANNOTATION_VALIDATION, + new String[] {"identifier", String.valueOf(identifier)}); + } + + // build vote + Date reportDate = new Date(); + Vote vote = buildVote(buildAgent(userId, AgentTypes.PERSON), reportDate); + + // 3. Check if the user has already reported this annotation + ModerationRecord moderationRecord = + getAnnotationService().findModerationRecordById(identifier); + if (moderationRecord == null) + moderationRecord = buildNewModerationRecord(identifier, reportDate); + else + validateVote(moderationRecord, vote); + + moderationRecord.addReport(vote); + moderationRecord.computeSummary(); + moderationRecord.setLastUpdated(reportDate); + + // update record in the database + ModerationRecord storedModeration = + getAnnotationService().storeModerationRecord(moderationRecord); + + // build response + MultiValueMap headers = new LinkedMultiValueMap(5); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + headers.add(HttpHeaders.ETAG, Long.toString(storedModeration.getLastUpdated().hashCode())); + // headers.add(HttpHeaders.LINK, + // "; rel=\"type\""); + headers.add(HttpHeaders.VARY, HttpHeaders.ACCEPT); + + ResponseEntity response = + new ResponseEntity(null, headers, HttpStatus.CREATED); + return response; + + } catch (HttpException e) { + // avoid wrapping HttpExceptions + throw e; + } catch (Exception e) { + throw new InternalServerException(e); } - - protected Vote buildVote(Agent user, Date reportDate) { - Vote vote = new BaseVote(); - vote.setCreated(reportDate); - vote.setUserId(user.getHttpUrl()); - return vote; + } + + // TODO :consider moving to persistent moderation record service + private void validateVote(ModerationRecord moderationRecord, Vote vote) + throws OperationAuthorizationException { + for (Vote existingVote : moderationRecord.getReportList()) { + if (vote.getUserId().equals(existingVote.getUserId())) + throw new OperationAuthorizationException( + "A report from the same users exists in database!", + I18nConstantsAnnotation.OPERATION_NOT_AUTHORIZED, new String[] {vote.getUserId()}); } + } + + protected ModerationRecord buildNewModerationRecord(long annoIdentifier, Date reportDate) { + // create moderation record + ModerationRecord moderationRecord = new BaseModerationRecord(); + moderationRecord.setIdentifier(annoIdentifier); + + // SET DEFAULTS + moderationRecord.setCreated(reportDate); + moderationRecord.setLastUpdated(reportDate); + + Summary summary = new BaseSummary(); + moderationRecord.setSummary(summary); + return moderationRecord; + } + + protected Vote buildVote(Agent user, Date reportDate) { + Vote vote = new BaseVote(); + vote.setCreated(reportDate); + vote.setUserId(user.getHttpUrl()); + return vote; + } } diff --git a/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/WebAnnotationProtocolRest.java b/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/WebAnnotationProtocolRest.java index 444f0653..5562cef5 100644 --- a/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/WebAnnotationProtocolRest.java +++ b/annotation-web/src/main/java/eu/europeana/annotation/web/service/controller/jsonld/WebAnnotationProtocolRest.java @@ -27,14 +27,13 @@ */ @RestController -@Api(tags = "Web Annotation Protocol", description=" ") +@Api(tags = "Web Annotation Protocol") public class WebAnnotationProtocolRest extends BaseJsonldRest { @RequestMapping(value = "/annotation/", method = RequestMethod.POST, produces = { HttpHeaders.CONTENT_TYPE_JSONLD_UTF8, HttpHeaders.CONTENT_TYPE_JSON_UTF8}) @ApiOperation(notes = SwaggerConstants.SAMPLES_JSONLD, value = "Create annotation", nickname = "createAnnotation", response = java.lang.Void.class) public ResponseEntity createAnnotation( -// @RequestParam(value = WebAnnotationFields.IDENTIFIER, required = false) String identifier, @RequestParam(value = WebAnnotationFields.INDEX_ON_CREATE, required = false, defaultValue = "true") boolean indexOnCreate, @RequestBody String annotation, HttpServletRequest request) @@ -72,7 +71,6 @@ public ResponseEntity updateAnnotation( Authentication authentication = verifyWriteAccess(Operations.UPDATE, request); -// String action = "put:/annotation/{identifier}[.{format}]"; return updateAnnotation(identifier, annotation, authentication, request); } @@ -87,7 +85,6 @@ public ResponseEntity deleteAnnotation( Authentication authentication = verifyWriteAccess(Operations.DELETE, request); -// String action = "delete:/annotation/{identifier}[.{format}]"; return deleteAnnotation(identifier, authentication, request); } diff --git a/annotation-web/src/main/java/eu/europeana/annotation/web/service/impl/AnnotationServiceImpl.java b/annotation-web/src/main/java/eu/europeana/annotation/web/service/impl/AnnotationServiceImpl.java index 47fc119e..e130d01a 100644 --- a/annotation-web/src/main/java/eu/europeana/annotation/web/service/impl/AnnotationServiceImpl.java +++ b/annotation-web/src/main/java/eu/europeana/annotation/web/service/impl/AnnotationServiceImpl.java @@ -270,7 +270,6 @@ private void mergeReferenceFields(PersistentAnnotation annotation, Annotation we } if (webAnnotation.getCanonical() != null) { - // TODO: #404 must never be overwritten if (StringUtils.isEmpty(annotation.getCanonical())) { annotation.setCanonical(webAnnotation.getCanonical()); } @@ -357,7 +356,7 @@ protected boolean removeFromIndex(Annotation annotation) { try { getSolrService().delete(annotation.getIdentifier()); } catch (Exception e) { - getLogger().error("Cannot remove annotation from solr index: " + annotation.getIdentifier(), + getLogger().error("Cannot remove annotation from solr index, id: " + annotation.getIdentifier(), e); return false; }