diff --git a/asTypescript/packages/client-http/src/HttpResourceAccessor.ts b/asTypescript/packages/client-http/src/HttpResourceAccessor.ts index 6135bec9..921669ee 100644 --- a/asTypescript/packages/client-http/src/HttpResourceAccessor.ts +++ b/asTypescript/packages/client-http/src/HttpResourceAccessor.ts @@ -279,10 +279,11 @@ export class HttpResourceAccessor implements ResourceAccessor { if (location.isPresent()) { try { url = new URL(location.get()); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Retrieving <" + url + "> yielded a Location header \"" + location.get() + "\" which doesn't parse as a URL: " + e.getMessage()); - } + }} + } // Determine whether the resource exists based on the response. Even if the resource // doesn't exist, additional context and processing is done to provide the appropriate @@ -354,7 +355,8 @@ export class HttpResourceAccessor implements ResourceAccessor { } catch (ex) { if (ex instanceof Exception) { throw new ShapeTreeException(500, ex.getMessage()); - } + }} + } /** @@ -453,10 +455,11 @@ export class HttpResourceAccessor implements ResourceAccessor { let managerUrlString: string = optManagerString.get(); try { return Optional.of(new URL(url, managerUrlString)); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Malformed relative URL <" + managerUrlString + "> (resolved from <" + url + ">)"); - } + }} + } /** @@ -482,10 +485,11 @@ export class HttpResourceAccessor implements ResourceAccessor { } try { managedResourceUrl = new URL(managerUrl, managedUrlString); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Can't calculate managed resource for shape tree manager <" + managerUrl + ">"); - } + }} + return managedResourceUrl; } diff --git a/asTypescript/packages/core/src/ManageableResource.ts b/asTypescript/packages/core/src/ManageableResource.ts index d87aba13..ab8a442d 100644 --- a/asTypescript/packages/core/src/ManageableResource.ts +++ b/asTypescript/packages/core/src/ManageableResource.ts @@ -44,10 +44,11 @@ export class ManageableResource extends InstanceResource { const rel: string = this.isContainer() ? ".." : "."; try { return new URL(this.getUrl(), rel); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Malformed focus node when resolving <" + rel + "> against <" + this.getUrl() + ">"); - } + }} + } public getManagerResourceUrl(): URL | null { diff --git a/asTypescript/packages/core/src/ShapeTree.ts b/asTypescript/packages/core/src/ShapeTree.ts index 8d8ddc1e..9ca7c047 100644 --- a/asTypescript/packages/core/src/ShapeTree.ts +++ b/asTypescript/packages/core/src/ShapeTree.ts @@ -115,7 +115,8 @@ export class ShapeTree { } catch (ex) { if (ex instanceof Exception) { throw new ShapeTreeException(500, "Error parsing ShEx schema - " + ex.getMessage()); - } + }} + } // Tell ShExJava we want to use Jena as our graph library let jenaRDF: JenaRDF = new org.apache.commons.rdf.jena.JenaRDF(); @@ -151,7 +152,8 @@ export class ShapeTree { } catch (ex) { if (ex instanceof MalformedURLException) { throw new ShapeTreeException(500, "Error reporting validation success on malformed URL <" + focusUriString + ">: " + ex.getMessage()); - } + }} + return new ValidationResult(valid, this, this, matchingFocusNode); } } diff --git a/asTypescript/packages/core/src/ShapeTreeAssignment.ts b/asTypescript/packages/core/src/ShapeTreeAssignment.ts index f7b47f23..ed8ccabc 100644 --- a/asTypescript/packages/core/src/ShapeTreeAssignment.ts +++ b/asTypescript/packages/core/src/ShapeTreeAssignment.ts @@ -56,7 +56,8 @@ export class ShapeTreeAssignment { } catch (ex) { if (ex instanceof NullPointerException || ex instanceof IllegalStateException) { throw new ShapeTreeException(500, "Failed to initialize shape tree assignment: " + ex.getMessage()); - } + }} + } public static getFromGraph(url: URL, managerGraph: Graph): ShapeTreeAssignment /* throws MalformedURLException, ShapeTreeException */ { diff --git a/asTypescript/packages/core/src/ShapeTreeFactory.ts b/asTypescript/packages/core/src/ShapeTreeFactory.ts index a74fe58a..d4a045a0 100644 --- a/asTypescript/packages/core/src/ShapeTreeFactory.ts +++ b/asTypescript/packages/core/src/ShapeTreeFactory.ts @@ -91,7 +91,8 @@ export class ShapeTreeFactory { } catch (ex) { if (ex instanceof MalformedURLException || ex instanceof ShapeTreeException) { throw new ShapeTreeException(500, "List <" + shapeTreeUrl + "> contains malformed URL: " + ex.getMessage()); - } + }} + } /** @@ -117,7 +118,8 @@ export class ShapeTreeFactory { } catch (ex) { if (ex instanceof MalformedURLException) { throw new ShapeTreeException(500, "ShapeTree <" + shapeTreeUrl + "> references malformed URL <" + referencedShapeTreeUrlString + ">: " + ex.getMessage()); - } + }} + let viaShapePath: string = getStringValue(resourceModel, referenceResource, ShapeTreeVocabulary.VIA_SHAPE_PATH); let viaPredicate: URL = getUrlValue(resourceModel, referenceResource, ShapeTreeVocabulary.VIA_PREDICATE, shapeTreeUrl); referencedShapeTree = new ShapeTreeReference(referencedShapeTreeUrl, viaShapePath, viaPredicate); @@ -147,7 +149,8 @@ export class ShapeTreeFactory { } catch (ex) { if (ex instanceof MalformedURLException) { throw new IllegalStateException("Malformed ShapeTree <" + shapeTreeUrl + ">: Jena URIResource <" + object + "> didn't parse as URL - " + ex.getMessage()); - } + }} + } else { throw new ShapeTreeException(500, "Malformed ShapeTree <" + shapeTreeUrl + ">: expected " + object + " to be a URL"); } diff --git a/asTypescript/packages/core/src/ShapeTreeManager.ts b/asTypescript/packages/core/src/ShapeTreeManager.ts index 3d9e64f0..e4833f73 100644 --- a/asTypescript/packages/core/src/ShapeTreeManager.ts +++ b/asTypescript/packages/core/src/ShapeTreeManager.ts @@ -106,7 +106,8 @@ export class ShapeTreeManager { } catch (ex) { if (ex instanceof MalformedURLException) { throw new IllegalStateException("Minted illegal URL <" + assignmentString + "> - " + ex.getMessage()); - } + }} + return assignmentUrl; } @@ -164,10 +165,11 @@ export class ShapeTreeManager { let assignment: ShapeTreeAssignment = null; try { assignment = ShapeTreeAssignment.getFromGraph(new URL(assignmentNode.getObject().getURI()), managerGraph); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Object of { " + s + " " + stAssignment + " " + assignmentNode.getObject() + " } must be a URL."); - } + }} + manager.assignments.add(assignment); } return manager; diff --git a/asTypescript/packages/core/src/ShapeTreeManagerDelta.ts b/asTypescript/packages/core/src/ShapeTreeManagerDelta.ts index 3cc7643f..d8f56288 100644 --- a/asTypescript/packages/core/src/ShapeTreeManagerDelta.ts +++ b/asTypescript/packages/core/src/ShapeTreeManagerDelta.ts @@ -82,7 +82,8 @@ export class ShapeTreeManagerDelta { } catch (ex) { if (ex instanceof URISyntaxException) { throw new ShapeTreeException(500, "Unable to convert assignment URLs for comparison: " + ex.getMessage()); - } + }} + if (assignmentUri === targetAssignmentUri) { return targetAssignment; } diff --git a/asTypescript/packages/core/src/contentloaders/HttpExternalDocumentLoader.ts b/asTypescript/packages/core/src/contentloaders/HttpExternalDocumentLoader.ts index e0175d42..24e1a535 100644 --- a/asTypescript/packages/core/src/contentloaders/HttpExternalDocumentLoader.ts +++ b/asTypescript/packages/core/src/contentloaders/HttpExternalDocumentLoader.ts @@ -33,6 +33,7 @@ export class HttpExternalDocumentLoader implements ExternalDocumentLoader { throw new ShapeTreeException(500, "Error retrieving <" + resourceUrl + ">: " + ex.getMessage()); } else if (ex instanceof URISyntaxException) { throw new ShapeTreeException(500, "Malformed URL <" + resourceUrl + ">: " + ex.getMessage()); - } + }} + } } diff --git a/asTypescript/packages/core/src/helpers/GraphHelper.ts b/asTypescript/packages/core/src/helpers/GraphHelper.ts index e7c0c07c..58aae5bf 100644 --- a/asTypescript/packages/core/src/helpers/GraphHelper.ts +++ b/asTypescript/packages/core/src/helpers/GraphHelper.ts @@ -77,10 +77,11 @@ export class GraphHelper { let reader: StringReader = new StringReader(rawContent); RDFDataMgr.read(model.getGraph(), reader, baseURI.toString(), GraphHelper.getLangForContentType(contentType)); return model; - } catch (ex) { - if (ex instanceof RiotException) { + } catch (rex) { + if (rex instanceof RiotException) { throw new ShapeTreeException(422, "Error processing input - " + rex.getMessage()); - } + }} + } /** @@ -164,7 +165,8 @@ export class GraphHelper { } catch (ex) { if (ex instanceof URISyntaxException) { throw new IllegalStateException("can't convert URL <" + url + "> to IRI: " + ex); - } + }} + } /** @@ -183,7 +185,8 @@ export class GraphHelper { } catch (ex) { if (ex instanceof MalformedURLException || ex instanceof URISyntaxException) { throw new IllegalStateException("Unable to remove fragment from URL: " + ex.getMessage()); - } + }} + } public static knownUrl(urlString: string): URL { @@ -192,6 +195,7 @@ export class GraphHelper { } catch (ex) { if (ex instanceof MalformedURLException) { throw new IllegalStateException("Expected known URL <" + urlString + "> to parse as valid URL - " + ex.toString()); - } + }} + } } diff --git a/asTypescript/packages/core/src/helpers/RequestHelper.ts b/asTypescript/packages/core/src/helpers/RequestHelper.ts index 884612f0..eea3674e 100644 --- a/asTypescript/packages/core/src/helpers/RequestHelper.ts +++ b/asTypescript/packages/core/src/helpers/RequestHelper.ts @@ -97,10 +97,11 @@ export class RequestHelper { try { const focusNodeUrl: URL = new URL(baseUrl, focusNodeUrlString); focusNodeUrls.add(focusNodeUrl); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Malformed focus node when resolving <" + focusNodeUrlString + "> against <" + baseUrl + ">"); - } + }} + } } return focusNodeUrls; @@ -120,10 +121,11 @@ export class RequestHelper { try { const targetShapeTreeUrl: URL = new URL(targetShapeTreeUrlString); targetShapeTreeUrls.add(targetShapeTreeUrl); - } catch (ex) { - if (ex instanceof MalformedURLException) { + } catch (e) { + if (e instanceof MalformedURLException) { throw new ShapeTreeException(500, "Malformed focus node when resolving <" + targetShapeTreeUrlString + "> against <" + baseUrl + ">"); - } + }} + } } return targetShapeTreeUrls; @@ -158,7 +160,8 @@ export class RequestHelper { } catch (ex) { if (ex instanceof MalformedURLException) { throw new ShapeTreeException(500, "normalized to malformed URL <" + urlString + "> - " + ex.getMessage()); - } + }} + } /** diff --git a/asTypescript/packages/javahttp/src/JavaHttpClient.ts b/asTypescript/packages/javahttp/src/JavaHttpClient.ts index 8bffef1e..b97a641c 100644 --- a/asTypescript/packages/javahttp/src/JavaHttpClient.ts +++ b/asTypescript/packages/javahttp/src/JavaHttpClient.ts @@ -42,7 +42,8 @@ export class JavaHttpClient implements HttpClient { } catch (ex) { if (ex instanceof NullPointerException) { log.error("Exception retrieving body string"); - } + }} + return new DocumentResponse(new ResourceAttributes(response.headers().map()), body, response.statusCode()); } @@ -75,16 +76,18 @@ export class JavaHttpClient implements HttpClient { let sc: SSLContext = null; try { sc = SSLContext.getInstance("TLSv1.2"); - } catch (ex) { - if (ex instanceof NoSuchAlgorithmException) { + } catch (e) { + if (e instanceof NoSuchAlgorithmException) { e.printStackTrace(); - } + }} + try { sc.init(null, trustAllCerts, new java.security.SecureRandom()); - } catch (ex) { - if (ex instanceof KeyManagementException) { + } catch (e) { + if (e instanceof KeyManagementException) { e.printStackTrace(); - } + }} + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier let validHosts: HostnameVerifier = new HostnameVerifier() { @@ -142,7 +145,8 @@ export class JavaHttpClient implements HttpClient { throw new ShapeTreeException(500, ex.getMessage()); } else if (ex instanceof URISyntaxException) { throw new ShapeTreeException(500, "Malformed URL <" + request.resourceURL + ">: " + ex.getMessage()); - } + }} + } protected static check(resp: java.net.http.HttpResponse): java.net.http.HttpResponse { diff --git a/asTypescript/packages/javahttp/src/JavaHttpClientFactory.ts b/asTypescript/packages/javahttp/src/JavaHttpClientFactory.ts index 755b4977..a0c171c5 100644 --- a/asTypescript/packages/javahttp/src/JavaHttpClientFactory.ts +++ b/asTypescript/packages/javahttp/src/JavaHttpClientFactory.ts @@ -39,7 +39,8 @@ export class JavaHttpClientFactory implements HttpClientFactory, ExternalDocumen } catch (ex) { if (ex instanceof Exception) { throw new ShapeTreeException(500, ex.getMessage()); - } + }} + } /** diff --git a/asTypescript/packages/javahttp/src/JavaHttpValidatingShapeTreeInterceptor.ts b/asTypescript/packages/javahttp/src/JavaHttpValidatingShapeTreeInterceptor.ts index 74c361f8..f13dea98 100644 --- a/asTypescript/packages/javahttp/src/JavaHttpValidatingShapeTreeInterceptor.ts +++ b/asTypescript/packages/javahttp/src/JavaHttpValidatingShapeTreeInterceptor.ts @@ -54,7 +54,8 @@ export class JavaHttpValidatingShapeTreeInterceptor { } else if (ex instanceof Exception) { log.error("Error processing shape tree request: ", ex); return createErrorResponse(new ShapeTreeException(500, ex.getMessage()), clientRequest); - } + }} + } else { log.warn("No handler for method [{}] - passing through request", shapeTreeRequest.getMethod()); return JavaHttpClient.check(httpClient.send(clientRequest, java.net.http.HttpResponse.BodyHandlers.ofString())); @@ -120,7 +121,8 @@ export class JavaHttpValidatingShapeTreeInterceptor { } catch (ex) { if (ex instanceof MalformedURLException) { throw new IllegalStateException("request has a malformed URL <" + request.uri() + ">: " + ex.getMessage()); - } + }} + } override public getHeaders(): ResourceAttributes { diff --git a/shapetrees-java-client-core/src/main/java/com/janeirodigital/shapetrees/client/core/ShapeTreeClient.java b/shapetrees-java-client-core/src/main/java/com/janeirodigital/shapetrees/client/core/ShapeTreeClient.java index 711cb833..553e81a1 100644 --- a/shapetrees-java-client-core/src/main/java/com/janeirodigital/shapetrees/client/core/ShapeTreeClient.java +++ b/shapetrees-java-client-core/src/main/java/com/janeirodigital/shapetrees/client/core/ShapeTreeClient.java @@ -84,14 +84,14 @@ public interface ShapeTreeClient { * @param context ShapeTreeContext that would be used for authentication purposes * @param targetResource The target resource to be created or updated * @param focusNodes One or more nodes/subjects to use as the focus for shape validation - * @param targetShapeTrees The shape trees that a proposed resource to be created should be validated against - * @param isContainer Specifies whether a newly created resource should be created as a container or not * @param bodyString String representation of the body of the resource to create or update * @param contentType Content type to parse the bodyString parameter as + * @param targetShapeTrees The shape trees that a proposed resource to be created should be validated against + * @param isContainer Specifies whether a newly created resource should be created as a container or not * @return DocumentResponse containing status and response header / attributes * @throws ShapeTreeException */ - DocumentResponse putManagedInstance(ShapeTreeContext context, URL targetResource, List focusNodes, List targetShapeTrees, Boolean isContainer, String bodyString, String contentType) throws ShapeTreeException; + DocumentResponse putManagedInstance(ShapeTreeContext context, URL targetResource, List focusNodes, String bodyString, String contentType, List targetShapeTrees, Boolean isContainer) throws ShapeTreeException; /** * Updates a resource via HTTP PUT that has been validated against an associated shape tree @@ -103,7 +103,7 @@ public interface ShapeTreeClient { * @return DocumentResponse containing status and response header / attributes * @throws ShapeTreeException */ - DocumentResponse putManagedInstance(ShapeTreeContext context, URL targetResource, List focusNodes, String bodyString, String contentType) throws ShapeTreeException; + DocumentResponse updateManagedInstance(ShapeTreeContext context, URL targetResource, List focusNodes, String bodyString, String contentType) throws ShapeTreeException; /** * Updates a resource via HTTP PATCH that has been validated against an associated shape tree diff --git a/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpResourceAccessor.java b/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpResourceAccessor.java index 6dd65df0..c35da237 100644 --- a/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpResourceAccessor.java +++ b/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpResourceAccessor.java @@ -97,7 +97,7 @@ public class HttpResourceAccessor implements ResourceAccessor { private ManageableInstance getInstanceFromMissingManageableResource(ShapeTreeContext context, MissingManageableResource missing) { - MissingManagerResource missingManager = new MissingManagerResource(missing, null); + MissingManagerResource missingManager = new MissingManagerResource(missing.getUrl(), missing); return new ManageableInstance(context, this, false, missing, missingManager); } @@ -327,7 +327,9 @@ public class HttpResourceAccessor implements ResourceAccessor { generateResource(URL url, DocumentResponse response) throws ShapeTreeException { // If a resource was created, ensure the URL returned in the Location header is valid - Optional location = response.getResourceAttributes().firstValue(HttpHeaders.LOCATION.getValue()); + Optional location = response.getResourceAttributes() == null + ? Optional.empty() + : response.getResourceAttributes().firstValue(HttpHeaders.LOCATION.getValue()); if (location.isPresent()) { try { url = new URL(location.get()); @@ -341,7 +343,7 @@ public class HttpResourceAccessor implements ResourceAccessor { // typed resource with adequate context to the caller final boolean exists = response.isExists(); final boolean container = isContainerFromHeaders(response.getResourceAttributes(), url); - final ResourceAttributes attributes = response.getResourceAttributes(); + final ResourceAttributes attributes = response.getResourceAttributes(); // TODO: could be null final ShapeTreeResourceType resourceType = getResourceTypeFromHeaders(response.getResourceAttributes()); final String name = calculateName(url); @@ -364,7 +366,7 @@ public class HttpResourceAccessor implements ResourceAccessor { if (exists) { return new ManagerResource(url, resourceType, attributes, body, name, true, managedResourceUrl); } else { - return new MissingManagerResource(url, resourceType, attributes, body, name, managedResourceUrl); + return new MissingManagerResource(managedResourceUrl, url, resourceType, attributes, body, name); } } else { // Look for presence of st:managedBy in link headers from response and get the target manager URL @@ -473,7 +475,9 @@ public class HttpResourceAccessor implements ResourceAccessor { private boolean isContainerFromHeaders(ResourceAttributes headers, URL url) { - List linkHeaders = headers.allValues(HttpHeaders.LINK.getValue()); + List linkHeaders = headers == null + ? Collections.emptyList() + : headers.allValues(HttpHeaders.LINK.getValue()); if (linkHeaders.isEmpty()) { return url.getPath().endsWith("/"); } @@ -495,7 +499,9 @@ public class HttpResourceAccessor implements ResourceAccessor { private ShapeTreeResourceType getResourceTypeFromHeaders(ResourceAttributes headers) { - List linkHeaders = headers.allValues(HttpHeaders.LINK.getValue()); + List linkHeaders = headers == null + ? null + : headers.allValues(HttpHeaders.LINK.getValue()); if (linkHeaders == null) { return null; } diff --git a/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpShapeTreeClient.java b/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpShapeTreeClient.java index a54d8365..f2f6c403 100644 --- a/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpShapeTreeClient.java +++ b/shapetrees-java-client-http/src/main/java/com/janeirodigital/shapetrees/client/http/HttpShapeTreeClient.java @@ -16,9 +16,13 @@ import lombok.extern.slf4j.Slf4j; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.riot.RDFWriter; +import org.apache.jena.riot.RIOT; +import java.io.ByteArrayOutputStream; import java.io.StringWriter; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; @@ -117,13 +121,13 @@ public DocumentResponse plantShapeTree(ShapeTreeContext context, URL targetResou ManageableResource manageableResource = instance.getManageableResource(); if (!manageableResource.isExists()) { - return new DocumentResponse(null, "Cannot find target resource to plant: " + targetResource, 404); + return new DocumentResponse(new ResourceAttributes(), "Cannot find target resource to plant: " + targetResource, 404); } ShapeTreeManager manager; URL managerResourceUrl = instance.getManagerResource().getUrl(); if (instance.isManaged()) { - manager = instance.getManagerResource().getManager(); + manager = instance.getManagerResource().getManager(); // TODO: could be null } else { manager = new ShapeTreeManager(managerResourceUrl); } @@ -141,14 +145,22 @@ public DocumentResponse plantShapeTree(ShapeTreeContext context, URL targetResou manager.addAssignment(assignment); // Get an RDF version of the manager stored in a turtle string - StringWriter sw = new StringWriter(); - RDFDataMgr.write(sw, manager.getGraph(), Lang.TURTLE); + + ByteArrayOutputStream asBytes = new ByteArrayOutputStream(); + RDFWriter.create() + .base(targetShapeTree.toString()) + .set(RIOT.symTurtleOmitBase, false) + .set(RIOT.symTurtleDirectiveStyle, "rdf11") + .lang(Lang.TTL) + .source(manager.getGraph()) + .output(asBytes); + String asString = new String(asBytes.toByteArray(), StandardCharsets.UTF_8); // Build an HTTP PUT request with the manager graph in turtle as the content body + link header HttpClient fetcher = HttpClientFactoryManager.getFactory().get(this.useClientShapeTreeValidation); ResourceAttributes headers = new ResourceAttributes(); headers.maybeSet(HttpHeaders.AUTHORIZATION.getValue(), context.getAuthorizationHeaderValue()); - return fetcher.fetchShapeTreeResponse(new HttpRequest("PUT", managerResourceUrl, headers, sw.toString(), "text/turtle")); + return fetcher.fetchShapeTreeResponse(new HttpRequest("PUT", managerResourceUrl, headers, asString, "text/turtle")); } @Override @@ -170,7 +182,7 @@ public DocumentResponse postManagedInstance(ShapeTreeContext context, URL parent // Create via HTTP PUT @Override - public DocumentResponse putManagedInstance(ShapeTreeContext context, URL resourceUrl, List focusNodes, List targetShapeTrees, Boolean isContainer, String bodyString, String contentType) throws ShapeTreeException { + public DocumentResponse putManagedInstance(ShapeTreeContext context, URL resourceUrl, List focusNodes, String bodyString, String contentType, List targetShapeTrees, Boolean isContainer) throws ShapeTreeException { if (context == null || resourceUrl == null) { throw new ShapeTreeException(500, "Must provide a valid context and target resource to create shape tree instance via PUT"); @@ -187,7 +199,7 @@ public DocumentResponse putManagedInstance(ShapeTreeContext context, URL resourc // Update via HTTP PUT @Override - public DocumentResponse putManagedInstance(ShapeTreeContext context, URL resourceUrl, List focusNodes, String bodyString, String contentType) throws ShapeTreeException { + public DocumentResponse updateManagedInstance(ShapeTreeContext context, URL resourceUrl, List focusNodes, String bodyString, String contentType) throws ShapeTreeException { if (context == null || resourceUrl == null) { throw new ShapeTreeException(500, "Must provide a valid context and target resource to update shape tree instance via PUT"); @@ -256,7 +268,7 @@ public DocumentResponse unplantShapeTree(ShapeTreeContext context, URL targetRes } // Remove assignment from manager that corresponds with the provided shape tree - ShapeTreeManager manager = instance.getManagerResource().getManager(); + ShapeTreeManager manager = instance.getManagerResource().getManager(); // TODO: could be null manager.removeAssignmentForShapeTree(targetShapeTree); String method; diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/DocumentResponse.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/DocumentResponse.java index dfc474bb..3c5c7010 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/DocumentResponse.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/DocumentResponse.java @@ -13,7 +13,9 @@ public class DocumentResponse { private final int statusCode; public Optional getContentType() { - return this.resourceAttributes.firstValue(HttpHeaders.CONTENT_TYPE.getValue()); + return this.resourceAttributes == null + ? Optional.empty() + : this.resourceAttributes.firstValue(HttpHeaders.CONTENT_TYPE.getValue()); } // TODO: lots of choices re non-404, not >= 4xx, not 3xx. not 201 (meaning there's no body) diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ManageableInstance.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ManageableInstance.java index caee906e..1c725729 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ManageableInstance.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ManageableInstance.java @@ -25,7 +25,7 @@ * is immutable. */ @Slf4j @Getter -public class ManageableInstance { +public class ManageableInstance { public static final String TEXT_TURTLE = "text/turtle"; private final ResourceAccessor resourceAccessor; diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/MissingManagerResource.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/MissingManagerResource.java index a7bb0f87..3181ec26 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/MissingManagerResource.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/MissingManagerResource.java @@ -12,23 +12,23 @@ public class MissingManagerResource extends ManagerResource { /** * Construct a missing manager resource based on a MissingManageableResource + * @param managedResourceUrl Corresponding URL of the resource that would be managed * @param manageable Missing manageable resource - * @param managedUrl Corresponding URL of the resource that would be managed */ - public MissingManagerResource(MissingManageableResource manageable, URL managedUrl) { - super(manageable.getUrl(), manageable.getResourceType(), manageable.getAttributes(), manageable.getBody(), manageable.getName(), manageable.isExists(), managedUrl); + public MissingManagerResource(URL managedResourceUrl, MissingManageableResource manageable) { + super(manageable.getUrl(), manageable.getResourceType(), manageable.getAttributes(), manageable.getBody(), manageable.getName(), manageable.isExists(), managedResourceUrl); } /** * Construct a missing manager resource. + * @param managedResourceUrl URL of the resource that would be managed * @param url URL of the resource * @param resourceType Identified shape tree resource type * @param attributes Associated resource attributes * @param body Body of the resource * @param name Name of the resource - * @param managedResourceUrl URL of the resource that would be managed */ - public MissingManagerResource(URL url, ShapeTreeResourceType resourceType, ResourceAttributes attributes, String body, String name, URL managedResourceUrl) { + public MissingManagerResource(URL managedResourceUrl, URL url, ShapeTreeResourceType resourceType, ResourceAttributes attributes, String body, String name) { super(url, resourceType, attributes, body, name, false, managedResourceUrl); } diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ResourceAttributes.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ResourceAttributes.java index 6f7c5bd2..f9a3d0d2 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ResourceAttributes.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ResourceAttributes.java @@ -179,7 +179,7 @@ public List allValues(String name) { List values = toMultimap().get(name); // Making unmodifiable list out of empty in order to make a list which // throws UOE unconditionally - return values != null ? values : List.of(); + return values != null ? values : List.of(); // TODO: some callers, e.g. HttpResourceAccessor.getResourceTypeFromHeaders, expect null } public String toString() { diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTree.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTree.java index 0cbf244c..38170266 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTree.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTree.java @@ -77,10 +77,10 @@ public ValidationResult validateResource(ManageableResource targetResource, List targetResource.getAttributes().firstValue(HttpHeaders.CONTENT_TYPE.getValue()).orElse(null)); } - return validateResource(targetResource.getName(), targetResource.getResourceType(), bodyGraph, focusNodeUrls); + return validateResource(targetResource.getName(), focusNodeUrls, targetResource.getResourceType(), bodyGraph); } - public ValidationResult validateResource(String requestedName, ShapeTreeResourceType resourceType, Graph bodyGraph, List focusNodeUrls) throws ShapeTreeException { + public ValidationResult validateResource(String requestedName, List focusNodeUrls, ShapeTreeResourceType resourceType, Graph bodyGraph) throws ShapeTreeException { // Check whether the proposed resource is the same type as what is expected by the shape tree if (!this.expectedResourceType.toString().equals(resourceType.getValue())) { @@ -122,7 +122,7 @@ public ValidationResult validateGraph(Graph graph, List focusNodeUrls) thro String shapeBody = shexShapeContents.getBody(); InputStream stream = new ByteArrayInputStream(shapeBody.getBytes(StandardCharsets.UTF_8)); - ShExCParser shexCParser = new ShExCParser(); + ShExCParser shexCParser = new ShExCParser(); // TODO: set base URL to this.shape try { schema = new ShexSchema(GlobalFactory.RDFFactory,shexCParser.getRules(stream),shexCParser.getStart()); if (SchemaCache.isInitialized()) { @@ -137,24 +137,24 @@ public ValidationResult validateGraph(Graph graph, List focusNodeUrls) thro JenaRDF jenaRDF = new org.apache.commons.rdf.jena.JenaRDF(); GlobalFactory.RDFFactory = jenaRDF; - ValidationAlgorithm validation = new RecursiveValidation(schema, jenaRDF.asGraph(graph)); + ValidationAlgorithm validator = new RecursiveValidation(schema, jenaRDF.asGraph(graph)); Label shapeLabel = new Label(GlobalFactory.RDFFactory.createIRI(this.shape.toString())); - if (!focusNodeUrls.isEmpty()) { // One or more focus nodes were provided for validation + if (!focusNodeUrls.isEmpty()) { // One or more focus nodes were provided for validator for (URL focusNodeUrl : focusNodeUrls) { // Evaluate each provided focus node IRI focusNode = GlobalFactory.RDFFactory.createIRI(focusNodeUrl.toString()); log.debug("Validating Shape Label = {}, Focus Node = {}", shapeLabel.toPrettyString(), focusNode.getIRIString()); - validation.validate(focusNode, shapeLabel); - boolean valid = validation.getTyping().isConformant(focusNode, shapeLabel); + validator.validate(focusNode, shapeLabel); + boolean valid = validator.getTyping().isConformant(focusNode, shapeLabel); if (valid) { return new ValidationResult(valid, this, this, focusNodeUrl); } } // None of the provided focus nodes were valid - this will return the last failure return new ValidationResult(false, this, "Failed to validate: " + shapeLabel.toPrettyString()); - } else { // No focus nodes were provided for validation, so all subject nodes will be evaluated + } else { // No focus nodes were provided for validator, so all subject nodes will be evaluated List evaluateNodes = GraphUtil.listSubjects(graph, Node.ANY, Node.ANY).toList(); @@ -162,17 +162,15 @@ public ValidationResult validateGraph(Graph graph, List focusNodeUrls) thro final String focusUriString = evaluateNode.getURI(); IRI node = GlobalFactory.RDFFactory.createIRI(focusUriString); - validation.validate(node, shapeLabel); - boolean valid = validation.getTyping().isConformant(node, shapeLabel); + validator.validate(node, shapeLabel); + boolean valid = validator.getTyping().isConformant(node, shapeLabel); if (valid) { - final URL matchingFocusNode; try { - matchingFocusNode = new URL(focusUriString); + return new ValidationResult(valid, this, this, new URL(focusUriString)); } catch (MalformedURLException ex) { - throw new ShapeTreeException(500, "Error reporting validation success on malformed URL <" + focusUriString + ">: " + ex.getMessage()); + throw new ShapeTreeException(500, "Error reporting validator success on malformed URL <" + focusUriString + ">: " + ex.getMessage()); } - return new ValidationResult(valid, this, this, matchingFocusNode); } } @@ -183,28 +181,25 @@ public ValidationResult validateGraph(Graph graph, List focusNodeUrls) thro } public ValidationResult validateContainedResource(ManageableResource containedResource) throws ShapeTreeException { - + // TODO: this same test gets performed in the call to the 2nd valdateContainedResource (after potentially parsing the graph) if (this.contains == null || this.contains.isEmpty()) { // TODO: say it can't be null? // The contained resource is permitted because this shape tree has no restrictions on what it contains return new ValidationResult(true, this, this, null); } - return validateContainedResource(containedResource, Collections.emptyList(), Collections.emptyList()); - - } - - public ValidationResult validateContainedResource(ManageableResource containedResource, List targetShapeTreeUrls, List focusNodeUrls) throws ShapeTreeException { - Graph containedResourceGraph = null; - if (containedResource.getResourceType() != ShapeTreeResourceType.NON_RDF) { + ShapeTreeResourceType resourceType = containedResource.getResourceType(); + if (resourceType != ShapeTreeResourceType.NON_RDF) { containedResourceGraph = GraphHelper.readStringIntoGraph(urlToUri(containedResource.getUrl()), containedResource.getBody(), containedResource.getAttributes().firstValue(HttpHeaders.CONTENT_TYPE.getValue()).orElse(null)); } - return validateContainedResource(containedResource.getName(), containedResource.getResourceType(), targetShapeTreeUrls, containedResourceGraph, focusNodeUrls); - + List targetShapeTreeUrls = Collections.emptyList(); + List focusNodeUrls = Collections.emptyList(); + String requestedName = containedResource.getName(); + return validateContainedResource(requestedName, resourceType, targetShapeTreeUrls, containedResourceGraph, focusNodeUrls); } public ValidationResult validateContainedResource(String requestedName, ShapeTreeResourceType resourceType, List targetShapeTreeUrls, Graph bodyGraph, List focusNodeUrls) throws ShapeTreeException { @@ -222,7 +217,7 @@ public ValidationResult validateContainedResource(String requestedName, ShapeTre if (this.contains.contains(targetShapeTreeUrl)) { ShapeTree targetShapeTree = ShapeTreeFactory.getShapeTree(targetShapeTreeUrl); // Evaluate the shape tree against the attributes of the proposed resources - ValidationResult result = targetShapeTree.validateResource(requestedName, resourceType, bodyGraph, focusNodeUrls); + ValidationResult result = targetShapeTree.validateResource(requestedName, focusNodeUrls, resourceType, bodyGraph); if (Boolean.TRUE.equals(result.getValid())) { // Return a successful validation result, including the matching shape tree return new ValidationResult(true, this, targetShapeTree, result.getMatchingFocusNode()); @@ -239,7 +234,7 @@ public ValidationResult validateContainedResource(String requestedName, ShapeTre if (containsShapeTree == null) { continue; } // Continue if the shape tree isn't gettable // Evaluate the shape tree against the attributes of the proposed resources - ValidationResult result = containsShapeTree.validateResource(requestedName, resourceType, bodyGraph, focusNodeUrls); + ValidationResult result = containsShapeTree.validateResource(requestedName, focusNodeUrls, resourceType, bodyGraph); // Continue if the proposed attributes were not a match if (Boolean.FALSE.equals(result.getValid())) { continue; } // Return the successful validation result @@ -251,14 +246,6 @@ public ValidationResult validateContainedResource(String requestedName, ShapeTre } - public Iterator getReferencedShapeTrees() throws ShapeTreeException { - return getReferencedShapeTrees(RecursionMethods.DEPTH_FIRST); - } - - public Iterator getReferencedShapeTrees(RecursionMethods recursionMethods) throws ShapeTreeException { - return getReferencedShapeTreesList(recursionMethods).iterator(); - } - // Return the list of shape tree contains by priority from most to least strict public List getPrioritizedContains() { @@ -268,6 +255,14 @@ public List getPrioritizedContains() { } + public Iterator getReferencedShapeTrees() throws ShapeTreeException { + return getReferencedShapeTrees(RecursionMethods.DEPTH_FIRST); + } + + public Iterator getReferencedShapeTrees(RecursionMethods recursionMethods) throws ShapeTreeException { + return getReferencedShapeTreesList(recursionMethods).iterator(); + } + private List getReferencedShapeTreesList(RecursionMethods recursionMethods) throws ShapeTreeException { if (recursionMethods.equals(RecursionMethods.BREADTH_FIRST)) { return getReferencedShapeTreesListBreadthFirst(); diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeFactory.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeFactory.java index 0503440e..1861b638 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeFactory.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeFactory.java @@ -121,27 +121,20 @@ private ShapeTreeFactory() { } ArrayList references = new ArrayList<>(); Property referencesProperty = resourceModel.createProperty(ShapeTreeVocabulary.REFERENCES); - if (shapeTreeNode.hasProperty(referencesProperty)) { - List referenceStatements = shapeTreeNode.listProperties(referencesProperty).toList(); + if (shapeTreeNode.hasProperty(referencesProperty)) { // TODO: arbitrarily pics from n objects where 1 expected + List referenceStatements = shapeTreeNode.listProperties(referencesProperty).toList(); // TODO: test coverage (never hit) for (Statement referenceStatement : referenceStatements) { Resource referenceResource = referenceStatement.getObject().asResource(); - final String referencedShapeTreeUrlString = getStringValue(resourceModel, referenceResource, ShapeTreeVocabulary.REFERENCES_SHAPE_TREE); - final URL referencedShapeTreeUrl; - ShapeTreeReference referencedShapeTree; - - try { - referencedShapeTreeUrl = new URL(referencedShapeTreeUrlString); - } catch (MalformedURLException ex) { - throw new ShapeTreeException(500, "ShapeTree <" + shapeTreeUrl + "> references malformed URL <" + referencedShapeTreeUrlString + ">: " + ex.getMessage()); + final URL referencedShapeTreeUrl = getUrlValue(resourceModel, referenceResource, ShapeTreeVocabulary.REFERENCES_SHAPE_TREE, shapeTreeUrl); + if (referencedShapeTreeUrl == null) { + throw new ShapeTreeException(400, "expected <" + shapeTreeUrl + "> reference " + referenceResource.toString() + " to have one <" + ShapeTreeVocabulary.REFERENCES_SHAPE_TREE + "> property"); } String viaShapePath = getStringValue(resourceModel, referenceResource, ShapeTreeVocabulary.VIA_SHAPE_PATH); URL viaPredicate = getUrlValue(resourceModel, referenceResource, ShapeTreeVocabulary.VIA_PREDICATE, shapeTreeUrl); - referencedShapeTree = new ShapeTreeReference(referencedShapeTreeUrl, viaShapePath, viaPredicate); - - references.add(referencedShapeTree); + references.add(new ShapeTreeReference(referencedShapeTreeUrl, viaShapePath, viaPredicate)); } } return references; diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManager.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManager.java index 6a8a6760..ce6ecf7f 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManager.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManager.java @@ -34,7 +34,7 @@ public class ShapeTreeManager { private final URL id; // Each ShapeTreeManager has one or more ShapeTreeAssignments - private final List assignments = new ArrayList<>(); + private final List assignments = new ArrayList<>(); // TODO: try Map, makes getContainingAssignments() redundant against getAssignments() /** * Constructor for a new ShapeTreeManager @@ -185,7 +185,7 @@ public static ShapeTreeManager getFromGraph(URL id, Graph managerGraph) throws S } else if (managerTriples.isEmpty()) { // Given the fact that a manager resource exists, there should never be a case where the manager resource // exists but no manager is found inside of it. - throw new IllegalStateException("No ShapeTreeManager instances found: " + managerTriples.size()); + throw new IllegalStateException("No ShapeTreeManager instances found: " + managerTriples.size()); // TODO: isn't that always 0? } // Get the URL of the ShapeTreeManager subject node @@ -214,7 +214,7 @@ public static ShapeTreeManager getFromGraph(URL id, Graph managerGraph) throws S } - public ShapeTreeAssignment getAssignmentForShapeTree(URL shapeTreeUrl) { + public ShapeTreeAssignment getAssignmentForShapeTree(URL shapeTreeUrl) { // TODO: return list of assignments with same ST but different roots if (this.assignments.isEmpty()) { return null; } diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManagerDelta.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManagerDelta.java index fed8779f..9d5f2ab7 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManagerDelta.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeManagerDelta.java @@ -101,7 +101,7 @@ public static ShapeTreeAssignment containsSameUrl(ShapeTreeAssignment assignment } public boolean allRemoved() { - return (!this.isUpdated() && this.removedAssignments.size() == this.existingManager.getAssignments().size()); + return (!this.isUpdated() && this.removedAssignments != null && this.removedAssignments.size() == this.existingManager.getAssignments().size()); } public boolean isUpdated() { diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeRequestHandler.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeRequestHandler.java index 192ba8a4..c65a7185 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeRequestHandler.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ShapeTreeRequestHandler.java @@ -31,8 +31,8 @@ public ShapeTreeRequestHandler(ResourceAccessor resourceAccessor) { public DocumentResponse manageShapeTree(ManageableInstance manageableInstance, ShapeTreeRequest shapeTreeRequest) throws ShapeTreeException { Optional validationResponse; - ShapeTreeManager updatedRootManager = RequestHelper.getIncomingShapeTreeManager(shapeTreeRequest, manageableInstance.getManagerResource()); - ShapeTreeManager existingRootManager = manageableInstance.getManagerResource().getManager(); + ShapeTreeManager updatedRootManager = RequestHelper.getIncomingShapeTreeManager(shapeTreeRequest, manageableInstance.getManagerResource()); // TODO: could be null + ShapeTreeManager existingRootManager = manageableInstance.getManagerResource().getManager(); // TODO: could be null // Determine assignments that have been removed, added, and/or updated ShapeTreeManagerDelta delta = ShapeTreeManagerDelta.evaluate(existingRootManager, updatedRootManager); @@ -131,7 +131,7 @@ public Optional createShapeTreeInstance(ManageableInstance man // if any of the provided focus nodes weren't matched validation must fail List unmatchedNodes = getUnmatchedFocusNodes(validationResults.values(), incomingFocusNodes); - if (!unmatchedNodes.isEmpty()) { return failValidation(new ValidationResult(false, "Failed to match target focus nodes: " + unmatchedNodes)); } + if (!unmatchedNodes.isEmpty()) { return failValidation(new ValidationResult(false, null,"Failed to match target focus nodes: " + unmatchedNodes)); } log.debug("Creating shape tree instance at {}", targetResourceUrl); @@ -168,7 +168,8 @@ public Optional updateShapeTreeInstance(ManageableInstance tar // All must pass for the update to validate ShapeTree shapeTree = ShapeTreeFactory.getShapeTree(assignment.getShapeTree()); URL managedResourceUrl = targetResource.getManageableResource().getUrl(); - ValidationResult validationResult = shapeTree.validateResource(null, shapeTreeRequest.getResourceType(), RequestHelper.getIncomingBodyGraph(shapeTreeRequest, managedResourceUrl, targetResource.getManageableResource()), RequestHelper.getIncomingFocusNodes(shapeTreeRequest, managedResourceUrl)); + Graph bodyGraph = RequestHelper.getIncomingBodyGraph(shapeTreeRequest, managedResourceUrl, targetResource.getManageableResource()); // TODO: could be null + ValidationResult validationResult = shapeTree.validateResource(null, RequestHelper.getIncomingFocusNodes(shapeTreeRequest, managedResourceUrl), shapeTreeRequest.getResourceType(), bodyGraph); if (Boolean.FALSE.equals(validationResult.isValid())) { return failValidation(validationResult); } } @@ -323,6 +324,7 @@ private ShapeTreeManager getManagerForAssignment(ManageableInstance manageableIn URL managerResourceUrl = manageableInstance.getManagerResource().getUrl(); // When at the top of the plant hierarchy, use the root manager from the initial plant request body + // TODO: rootManager can be null so method could return null (does not in any test) if (atRootOfPlantHierarchy(rootAssignment, manageableInstance.getManageableResource())) { return rootManager; } if (!manageableInstance.getManagerResource().isExists()) { @@ -383,7 +385,7 @@ private ShapeTreeManager getRootManager(ShapeTreeContext shapeTreeContext, Shape // Return a root shape tree manager associated with a given shape tree assignment private ShapeTreeAssignment getRootAssignment(ShapeTreeContext shapeTreeContext, ShapeTreeAssignment assignment) throws ShapeTreeException { - ShapeTreeManager rootManager = getRootManager(shapeTreeContext, assignment); + ShapeTreeManager rootManager = getRootManager(shapeTreeContext, assignment); // TODO: could be null for (ShapeTreeAssignment rootAssignment : rootManager.getAssignments()) { if (rootAssignment.getUrl() != null && rootAssignment.getUrl().equals(assignment.getRootAssignment())) { @@ -485,7 +487,8 @@ private DocumentResponse successfulValidation() { } private Optional failValidation(ValidationResult validationResult) { - return Optional.of(new DocumentResponse(new ResourceAttributes(), validationResult.getMessage(),422)); + String message = validationResult.getMessage() != null ? validationResult.getMessage() : "Unspecified validation failure"; + return Optional.of(new DocumentResponse(new ResourceAttributes(), message,422)); } } diff --git a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ValidationResult.java b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ValidationResult.java index 316bbf1e..f5d3f360 100644 --- a/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ValidationResult.java +++ b/shapetrees-java-core/src/main/java/com/janeirodigital/shapetrees/core/ValidationResult.java @@ -19,6 +19,7 @@ public Boolean isValid() { return (this.valid != null && this.valid); } + /* public ValidationResult(Boolean valid, String message) { this.valid = valid; this.message = message; @@ -36,6 +37,7 @@ public ValidationResult(Boolean valid, ShapeTree validatingShapeTree) { this.managingAssignment = null; this.matchingFocusNode = null; } + */ public ValidationResult(Boolean valid, ShapeTree validatingShapeTree, String message) { this.valid = valid; @@ -46,6 +48,7 @@ public ValidationResult(Boolean valid, ShapeTree validatingShapeTree, String mes this.matchingFocusNode = null; } + /* public ValidationResult(Boolean valid, ShapeTree validatingShapeTree, URL matchingFocusNode) { this.valid = valid; this.message = null; @@ -54,6 +57,7 @@ public ValidationResult(Boolean valid, ShapeTree validatingShapeTree, URL matchi this.managingAssignment = null; this.matchingFocusNode = matchingFocusNode; } + */ public ValidationResult(Boolean valid, ShapeTree validatingShapeTree, ShapeTree matchingShapeTree, URL matchingFocusNode) { this.valid = valid; diff --git a/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/ShapeTreeValidationTests.java b/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/ShapeTreeValidationTests.java index 7f64cd6b..4ca5fedc 100644 --- a/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/ShapeTreeValidationTests.java +++ b/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/ShapeTreeValidationTests.java @@ -67,13 +67,13 @@ void validateExpectsContainerType() { ValidationResult result; ShapeTree shapeTree = ShapeTreeFactory.getShapeTree(toUrl(server, "/static/shapetrees/validation/shapetree#ExpectsContainerTree")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.CONTAINER, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.CONTAINER, null); Assertions.assertTrue(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.RESOURCE, null); Assertions.assertFalse(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.NON_RDF, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.NON_RDF, null); Assertions.assertFalse(result.isValid()); } @@ -86,13 +86,13 @@ void validateExpectsResourceType() { ValidationResult result; ShapeTree shapeTree = ShapeTreeFactory.getShapeTree(toUrl(server, "/static/shapetrees/validation/shapetree#ExpectsResourceTree")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.RESOURCE, null); Assertions.assertTrue(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.CONTAINER, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.CONTAINER, null); Assertions.assertFalse(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.NON_RDF, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.NON_RDF, null); Assertions.assertFalse(result.isValid()); } @@ -105,13 +105,13 @@ void validateExpectsNonRDFResourceType() { ValidationResult result; ShapeTree shapeTree = ShapeTreeFactory.getShapeTree(toUrl(server, "/static/shapetrees/validation/shapetree#ExpectsNonRDFResourceTree")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.NON_RDF, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.NON_RDF, null); Assertions.assertTrue(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.RESOURCE, null); Assertions.assertFalse(result.isValid()); - result = shapeTree.validateResource(null, ShapeTreeResourceType.CONTAINER, null, null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.CONTAINER, null); Assertions.assertFalse(result.isValid()); } @@ -124,10 +124,10 @@ void validateLabel() { ValidationResult result; ShapeTree shapeTree = ShapeTreeFactory.getShapeTree(toUrl(server, "/static/shapetrees/validation/shapetree#LabelTree")); - result = shapeTree.validateResource("resource-name", ShapeTreeResourceType.RESOURCE, null, null); + result = shapeTree.validateResource("resource-name", null, ShapeTreeResourceType.RESOURCE, null); Assertions.assertTrue(result.isValid()); - result = shapeTree.validateResource("invalid-name", ShapeTreeResourceType.RESOURCE, null, null); + result = shapeTree.validateResource("invalid-name", null, ShapeTreeResourceType.RESOURCE, null); Assertions.assertFalse(result.isValid()); } @@ -143,11 +143,11 @@ void validateShape() { // Validate shape with focus node List focusNodeUrls = List.of(toUrl(server, "/validation/valid-resource#foo")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource")), focusNodeUrls); + result = shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource"))); Assertions.assertTrue(result.isValid()); // Validate shape without focus node - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource")), null); + result = shapeTree.validateResource(null, null, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource"))); Assertions.assertTrue(result.isValid()); } @@ -164,7 +164,7 @@ void failToValidateShape() { // Pass in body content that will fail validation of the shape associated with FooTree List focusNodeUrls = List.of(toUrl(server,"/validation/valid-resource#foo")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, getInvalidFooBodyGraph(toUrl(server, "/validation/valid-resource")), focusNodeUrls); + result = shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, getInvalidFooBodyGraph(toUrl(server, "/validation/valid-resource"))); Assertions.assertFalse(result.isValid()); } @@ -183,7 +183,7 @@ void failToValidateMissingShape() { // Catch exception thrown when a shape in a shape tree cannot be found List focusNodeUrls = List.of(toUrl(server,"/validation/valid-resource#foo")); - Assertions.assertThrows(ShapeTreeException.class, () -> shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, fooBodyGraph, focusNodeUrls)); + Assertions.assertThrows(ShapeTreeException.class, () -> shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, fooBodyGraph)); } @@ -201,7 +201,7 @@ void failToValidateMalformedShape() { // Catch exception thrown when a shape in a shape tree is invalid List focusNodeUrls = List.of(toUrl(server,"/validation/valid-resource#foo")); - Assertions.assertThrows(ShapeTreeException.class, () -> shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, fooBodyGraph, focusNodeUrls)); + Assertions.assertThrows(ShapeTreeException.class, () -> shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, fooBodyGraph)); } @@ -238,7 +238,7 @@ void validateShapeBeforeCaching() { // Validate shape with focus node List focusNodeUrls = List.of(toUrl(server,"/validation/valid-resource#foo")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource")), focusNodeUrls); + result = shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource"))); Assertions.assertTrue(result.isValid()); } @@ -258,7 +258,7 @@ void validateShapeAfterCaching() { // Validate shape with focus node List focusNodeUrls = List.of(toUrl(server,"/validation/valid-resource#foo")); - result = shapeTree.validateResource(null, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource")), focusNodeUrls); + result = shapeTree.validateResource(null, focusNodeUrls, ShapeTreeResourceType.RESOURCE, getFooBodyGraph(toUrl(server, "/validation/valid-resource"))); Assertions.assertTrue(result.isValid()); } diff --git a/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/clienthttp/AbstractHttpClientProjectTests.java b/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/clienthttp/AbstractHttpClientProjectTests.java index 576265e0..953e62fd 100644 --- a/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/clienthttp/AbstractHttpClientProjectTests.java +++ b/shapetrees-java-tests/src/test/java/com/janeirodigital/shapetrees/tests/clienthttp/AbstractHttpClientProjectTests.java @@ -259,7 +259,7 @@ void updateProjectInProjects() { // Update the project-1 container as a shape tree instance. // 1. Will be validated by the parent ProjectCollectionTree planted on /data/projects/ // 2. Will have a manager/assignment created for it as an instance of ProjectTree - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, getProjectOneUpdatedBodyGraph(), TEXT_TURTLE); + DocumentResponse response = shapeTreeClient.updateManagedInstance(context, targetResource, focusNodes, getProjectOneUpdatedBodyGraph(), TEXT_TURTLE); Assertions.assertEquals(200, response.getStatusCode()); } @@ -284,7 +284,7 @@ void failToCreateMalformedProject() { // Create the project-1 container as a shape tree instance via PUT // 1. Will be validated by the parent ProjectCollectionTree planted on /data/projects/ - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, targetShapeTrees, true, getProjectOneMalformedBodyGraph(), TEXT_TURTLE); + DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, getProjectOneMalformedBodyGraph(), TEXT_TURTLE, targetShapeTrees, true); // 2. Will fail validation because the body content doesn't validate against the assigned shape Assertions.assertEquals(422, response.getStatusCode()); @@ -313,7 +313,7 @@ void failToUpdateMalformedProject() { // Update the project-1 container as a shape tree instance via PUT // 1. Will be validated by the parent ProjectCollectionTree planted on /data/projects/ - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, getProjectOneMalformedBodyGraph(), TEXT_TURTLE); + DocumentResponse response = shapeTreeClient.updateManagedInstance(context, targetResource, focusNodes, getProjectOneMalformedBodyGraph(), TEXT_TURTLE); // 2. Will fail validation because the body content doesn't validate against the assigned shape Assertions.assertEquals(422, response.getStatusCode()); @@ -346,7 +346,7 @@ void createMilestoneInProjectWithPut() { // Create the milestone-3 container in /projects/project-1/ as a shape tree instance using PUT to create // 1. Will be validated by the parent ProjectTree planted on /data/projects/project-1/ // 2. Will have a manager/assignment created for it as an instance of MilestoneTree - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, targetShapeTrees, true, getMilestoneThreeBodyGraph(), TEXT_TURTLE); + DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, focusNodes, getMilestoneThreeBodyGraph(), TEXT_TURTLE, targetShapeTrees, true); Assertions.assertEquals(201, response.getStatusCode()); } @@ -540,7 +540,7 @@ void createAttachmentInTask() { URL targetResource = toUrl(server, "/data/projects/project-1/milestone-3/task-48/attachment-48"); List targetShapeTrees = Arrays.asList(toUrl(server, "/static/shapetrees/project/shapetree#AttachmentTree")); - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, null, targetShapeTrees, false, null, "application/octet-stream"); + DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, null, null, "application/octet-stream", targetShapeTrees, false); Assertions.assertEquals(201, response.getStatusCode()); } @@ -575,7 +575,7 @@ void createSecondAttachmentInTask() { URL targetResource = toUrl(server, "/data/projects/project-1/milestone-3/task-48/random.png"); List targetShapeTrees = Arrays.asList(toUrl(server, "/static/shapetrees/project/shapetree#AttachmentTree")); - DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, null, targetShapeTrees, false, null, "application/octet-stream"); + DocumentResponse response = shapeTreeClient.putManagedInstance(context, targetResource, null, null, "application/octet-stream", targetShapeTrees, false); Assertions.assertEquals(201, response.getStatusCode()); }