/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.trellisldp.http.impl;

import static java.util.Arrays.asList;
import static java.util.Date.from;
import static java.util.Objects.nonNull;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static javax.ws.rs.core.Response.Status.GONE;
import static javax.ws.rs.core.Response.status;
import static org.apache.commons.rdf.api.RDFSyntax.JSONLD;
import static org.apache.commons.rdf.api.RDFSyntax.NTRIPLES;
import static org.apache.commons.rdf.api.RDFSyntax.TURTLE;
import static org.trellisldp.api.RDFUtils.getInstance;
import static org.trellisldp.vocabulary.LDP.Resource;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.apache.commons.rdf.api.RDF;
import org.apache.commons.rdf.api.RDFSyntax;
import org.trellisldp.api.AuditService;
import org.trellisldp.api.ConstraintService;
import org.trellisldp.api.Resource;
import org.trellisldp.api.ResourceService;
import org.trellisldp.http.domain.LdpRequest;

/**
 * @author acoburn
 */
public class BaseLdpHandler {

    protected static final RDF rdf = getInstance();

    protected static Optional<AuditService> audit = loadFirst(AuditService.class);

    protected static final List<ConstraintService> constraintServices = new ArrayList<>();

    static {
        ServiceLoader.load(ConstraintService.class).forEach(constraintServices::add);
    }

    protected static final List<RDFSyntax> SUPPORTED_RDF_TYPES = asList(TURTLE, JSONLD, NTRIPLES);

    protected final Map<String, String> partitions;
    protected final LdpRequest req;
    protected final ResourceService resourceService;

    /**
     * A base class for response handling
     * @param partitions the partitions
     * @param req the LDP request
     * @param resourceService the resource service
     */
    public BaseLdpHandler(final Map<String, String> partitions, final LdpRequest req,
            final ResourceService resourceService) {
        this.partitions = partitions;
        this.req = req;
        this.resourceService = resourceService;
    }

    /**
     * Check if this is a deleted resource, and if so return an appropriate response
     * @param res the resource
     * @param identifier the identifier
     * @throws WebApplicationException a 410 Gone exception
     */
    protected static void checkDeleted(final Resource res, final String identifier) {
       if (RdfUtils.isDeleted(res)) {
            throw new WebApplicationException(status(GONE)
                    .links(MementoResource.getMementoLinks(identifier, res.getMementos())
                    .toArray(Link[]::new)).build());
        }
    }

    /**
     * Check the request for a cache-related response
     * @param request the request
     * @param modified the modified time
     * @param etag the etag
     * @throws WebApplicationException either a 412 Precondition Failed or a 304 Not Modified, depending on the context.
     */
    protected static void checkCache(final Request request, final Instant modified, final EntityTag etag) {
        final ResponseBuilder builder = request.evaluatePreconditions(from(modified), etag);
        if (nonNull(builder)) {
            throw new WebApplicationException(builder.build());
        }
    }

    // TODO - JDK9 replace with ServiceLoader::loadFirst
    private static <T> Optional<T> loadFirst(final Class<T> service) {
        final Iterator<T> iter = ServiceLoader.load(service).iterator();
        if (iter.hasNext()) {
            return of(iter.next());
        }
        return empty();
    }
}

@@ -709,48 +709,8 @@
 ll;%0A
-import static java.util.Optional.empty;%0A
 impo
@@ -4203,33 +4203,18 @@
     
-final Iterator%3CT%3E iter = 
+return of(
 Serv
@@ -4251,107 +4251,54 @@
 or()
-;%0A        if (iter.hasNext()) %7B%0A            return of(iter.next());%0A        %7D%0A        return empty(
+).filter(Iterator::hasNext).map(Iterator::next
 );%0A 

Simplify service loader