// Path: fcrepo-api-x-model/src/main/java/org/fcrepo/apix/model/Extension.java
// public interface Extension {
// 
//     /**
//      * RDF type this extension binds to.
//      *
//      * @return URI of the <code>rdf:type</code> this extension binds to.
//      */
//     public URI bindingClass();
// 
//     /**
//      * Determine if this extension exposes services.
//      *
//      * @return true if the extension exposes services
//      */
//     public boolean isExposing();
// 
//     /**
//      * Determine if this extension intercepts requests.
//      *
//      * @return true if the extension intercepts requests.
//      */
//     public boolean isIntercepting();
// 
//     /**
//      * Get specification for exposed services.
//      *
//      * @return Service exposure specification.
//      */
//     public ServiceExposureSpec exposed();
// 
//     /**
//      * Get specification for intercepting modality.
//      *
//      * @return Specification.
//      */
//     public Spec intercepted();
// 
//     /**
//      * The URI (location) of the extension.
//      * <p>
//      * This is a potentially more lightweight operation than <code>getResource().uri()</code>
//      * </p>
//      *
//      * @return its resolvable URI.
//      */
//     public URI uri();
// 
//     /**
//      * Underlying RDF representation of an extension.
//      *
//      * @return A serialization of the extension resource.
//      */
//     public WebResource getResource();
// 
//     /**
//      * Implementation specification for an extension.
//      */
//     public interface Spec {
// 
//         /**
//          * Set of consumed services.
//          *
//          * @return Non-null set.
//          */
//         public Set<URI> consumed();
// 
//     }
// 
//     /**
//      * Implementation specification for a service-exposing specification.
//      */
//     public interface ServiceExposureSpec extends Spec {
// 
//         /**
//          * The URI naming the exposed service.
//          * <p>
//          * This is not an endpoint URI, it is the URI which names the service in the abstract sense. A lookup in a
//          * {@link org.fcrepo.apix.model.components.ServiceRegistry} by URI can be expected to provide more information
//          * </p>
//          *
//          * @return the exposed service URI.
//          */
//         public URI exposedService();
// 
//         /**
//          * URI the service is exposed at.
//          * <p>
//          * May be absolute or relative. If relative, the {@link org.fcrepo.apix.model.components.Routing} component
//          * will use this to mint the resolvable URI a service is exposed at.
//          * </p>
//          *
//          * @return service exposure URI.
//          */
//         public URI exposedAt();
// 
//         /**
//          * The scope of the exposed service.
//          *
//          * @return scope (external, repository, resource)
//          */
//         public Scope scope();
//     }
// 
//     public enum Scope {
//         RESOURCE,
//         REPOSITORY,
//         EXTERNAL
//     }
// }
// 
// Path: fcrepo-api-x-model/src/main/java/org/fcrepo/apix/model/components/RoutingFactory.java
// public interface RoutingFactory {
// 
//     /**
//      * Answers a {@link Routing} for the requested resource.
//      *
//      * @param requestUri the URI of the requested resource
//      * @return the {@code Routing}
//      */
//     Routing of(URI requestUri);
// 
// }
// 
// Path: fcrepo-api-x-routing/src/main/java/org/fcrepo/apix/routing/Util.java
// public static URI append(final Object... segments) {
//     return URI.create(
//             Arrays.stream(segments)
//                     .reduce((a, b) -> String.join("/", segment(a.toString()), terminal(b.toString())))
//                     .get().toString());
// }


import org.fcrepo.apix.model.Extension;
import org.fcrepo.apix.model.components.ResourceNotFoundException;
import org.fcrepo.apix.model.components.Routing;
import org.fcrepo.apix.model.components.RoutingFactory;
import java.net.URI;
import static org.fcrepo.apix.routing.Util.append;
                if (path == null || path.equals("")) {
                    return append(exposedBaseURI(), exposePath, spec.exposedAt());
                }
                return append(exposedBaseURI(), exposePath, path, spec.exposedAt());
            default:
                throw new RuntimeException("Unknown service exposure scope " + spec.scope());
        }
    }

    @Override
    public URI endpointFor(final Extension.ServiceExposureSpec spec, final URI onResource) {
        return endpointFor(spec, resourcePath(onResource));
    }

    @Override
    public URI serviceDocFor(final URI resource) {
        return serviceDocFor(resourcePath(resource));
    }

    @Override
    public URI serviceDocFor(final String resourcePath) {
        return append(exposedBaseURI(), discoveryPath, resourcePath);
    }

    @Override
    public String resourcePath(final URI resourceURI) {

        final String r = resourceURI.toString();

        if (r.startsWith(fcrepoBaseURI.toString())) {
// Path: fcrepo-api-x-model/src/main/java/org/fcrepo/apix/model/Extension.java
// public interface Extension {
// 
//     /**
//      * RDF type this extension binds to.
//      *
//      * @return URI of the <code>rdf:type</code> this extension binds to.
//      */
//     public URI bindingClass();
// 
//     /**
//      * Determine if this extension exposes services.
//      *
//      * @return true if the extension exposes services
//      */
//     public boolean isExposing();
// 
//     /**
//      * Determine if this extension intercepts requests.
//      *
//      * @return true if the extension intercepts requests.
//      */
//     public boolean isIntercepting();
// 
//     /**
//      * Get specification for exposed services.
//      *
//      * @return Service exposure specification.
//      */
//     public ServiceExposureSpec exposed();
// 
//     /**
//      * Get specification for intercepting modality.
//      *
//      * @return Specification.
//      */
//     public Spec intercepted();
// 
//     /**
//      * The URI (location) of the extension.
//      * <p>
//      * This is a potentially more lightweight operation than <code>getResource().uri()</code>
//      * </p>
//      *
//      * @return its resolvable URI.
//      */
//     public URI uri();
// 
//     /**
//      * Underlying RDF representation of an extension.
//      *
//      * @return A serialization of the extension resource.
//      */
//     public WebResource getResource();
// 
//     /**
//      * Implementation specification for an extension.
//      */
//     public interface Spec {
// 
//         /**
//          * Set of consumed services.
//          *
//          * @return Non-null set.
//          */
//         public Set<URI> consumed();
// 
//     }
// 
//     /**
//      * Implementation specification for a service-exposing specification.
//      */
//     public interface ServiceExposureSpec extends Spec {
// 
//         /**
//          * The URI naming the exposed service.
//          * <p>
//          * This is not an endpoint URI, it is the URI which names the service in the abstract sense. A lookup in a
//          * {@link org.fcrepo.apix.model.components.ServiceRegistry} by URI can be expected to provide more information
//          * </p>
//          *
//          * @return the exposed service URI.
//          */
//         public URI exposedService();
// 
//         /**
//          * URI the service is exposed at.
//          * <p>
//          * May be absolute or relative. If relative, the {@link org.fcrepo.apix.model.components.Routing} component
//          * will use this to mint the resolvable URI a service is exposed at.
//          * </p>
//          *
//          * @return service exposure URI.
//          */
//         public URI exposedAt();
// 
//         /**
//          * The scope of the exposed service.
//          *
//          * @return scope (external, repository, resource)
//          */
//         public Scope scope();
//     }
// 
//     public enum Scope {
//         RESOURCE,
//         REPOSITORY,
//         EXTERNAL
//     }
// }
// 
// Path: fcrepo-api-x-model/src/main/java/org/fcrepo/apix/model/components/RoutingFactory.java
// public interface RoutingFactory {
// 
//     /**
//      * Answers a {@link Routing} for the requested resource.
//      *
//      * @param requestUri the URI of the requested resource
//      * @return the {@code Routing}
//      */
//     Routing of(URI requestUri);
// 
// }
// 
// Path: fcrepo-api-x-routing/src/main/java/org/fcrepo/apix/routing/Util.java
// public static URI append(final Object... segments) {
//     return URI.create(
//             Arrays.stream(segments)
//                     .reduce((a, b) -> String.join("/", segment(a.toString()), terminal(b.toString())))
//                     .get().toString());
// }


// Path: fcrepo-api-x-routing/src/main/java/org/fcrepo/apix/routing/impl/RoutingPrototype.java
import org.fcrepo.apix.model.Extension;
import org.fcrepo.apix.model.components.ResourceNotFoundException;
import org.fcrepo.apix.model.components.Routing;
import org.fcrepo.apix.model.components.RoutingFactory;
import java.net.URI;
import static org.fcrepo.apix.routing.Util.append;

                if (path == null || path.equals("")) {
                    return append(exposedBaseURI(), exposePath, spec.exposedAt());
                }
                return append(exposedBaseURI(), exposePath, path, spec.exposedAt());
            default:
                throw new RuntimeException("Unknown service exposure scope " + spec.scope());
        }
    }

    @Override
    public URI endpointFor(final Extension.ServiceExposureSpec spec, final URI onResource) {
        return endpointFor(spec, resourcePath(onResource));
    }

    @Override
    public URI serviceDocFor(final URI resource) {
        return serviceDocFor(resourcePath(resource));
    }

    @Override
    public URI serviceDocFor(final String resourcePath) {
        return append(exposedBaseURI(), discoveryPath, resourcePath);
    }

    @Override
    public String resourcePath(final URI resourceURI) {

        final String r = resourceURI.toString();

        if (r.startsWith(fcrepoBaseURI.toString())) {
            return "/" + fcrepoBaseURI.relativize(resourceURI).getPath();