001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.client;
019
020import static org.fcrepo.client.FedoraHeaderConstants.ACCEPT;
021import static org.fcrepo.client.FedoraHeaderConstants.IF_MODIFIED_SINCE;
022import static org.fcrepo.client.FedoraHeaderConstants.IF_NONE_MATCH;
023import static org.fcrepo.client.FedoraHeaderConstants.PREFER;
024import static org.fcrepo.client.FedoraHeaderConstants.RANGE;
025import java.net.URI;
026import java.time.Instant;
027import java.util.List;
028import java.util.StringJoiner;
029import java.util.stream.Collectors;
030
031import org.apache.http.client.methods.HttpRequestBase;
032
033/**
034 * Builds a GET request to retrieve the content of a resource from the Fedora HTTP API
035 *
036 * @author bbpennel
037 */
038public class GetBuilder extends RetrieveRequestBuilder {
039
040    /**
041     * Construct a GetBuilder
042     *
043     * @param uri the target
044     * @param client the client for this request
045     */
046    public GetBuilder(final URI uri, final FcrepoClient client) {
047        super(uri, client);
048    }
049
050    @Override
051    protected HttpRequestBase createRequest() {
052        return HttpMethods.GET.createRequest(targetUri);
053    }
054
055    /**
056     * Add the accept header to this request to negotiate the response format.
057     *
058     * @param mediaType media type to set as the accept header. It should be a value from one of the allowed RDF
059     *        source formats supported by Fedora.
060     * @return this builder
061     */
062    public GetBuilder accept(final String mediaType) {
063        if (mediaType != null) {
064            request.setHeader(ACCEPT, mediaType);
065        }
066        return this;
067    }
068
069    /**
070     * Set the byte range of content to retrieve
071     *
072     * @param rangeStart beginning byte index
073     * @param rangeEnd ending byte index
074     * @return this builder
075     */
076    public GetBuilder range(final Long rangeStart, final Long rangeEnd) {
077        if (rangeStart != null || rangeEnd != null) {
078            String range = "bytes=";
079            if (rangeStart != null && rangeStart.longValue() > -1L) {
080                range += rangeStart.toString();
081            }
082            range += "-";
083            if (rangeEnd != null && rangeEnd.longValue() > -1L) {
084                range += rangeEnd.toString();
085            }
086            request.setHeader(RANGE, range);
087        }
088        return this;
089    }
090
091    /**
092     * Set the prefer header for this request to representation, to indicate that links to other resources and their
093     * properties should also be included.
094     *
095     * @return this builder
096     */
097    public GetBuilder preferRepresentation() {
098        request.setHeader(PREFER, buildPrefer("representation", null, null));
099        return this;
100    }
101
102    /**
103     * Set the prefer header for this request to representation, to indicate that links to other resources and their
104     * properties should also be included. The set of properties returned can be further specified by providing lists
105     * of LDP defined preferences to omit or include.
106     *
107     * @param includeUris URIs of LDP defined preferences to include
108     * @param omitUris URIs of LDP defined preferences to omit
109     * @return this builder
110     */
111    public GetBuilder preferRepresentation(final List<URI> includeUris, final List<URI> omitUris) {
112        request.setHeader(PREFER, buildPrefer("representation", includeUris, omitUris));
113        return this;
114    }
115
116    private String buildPrefer(final String prefer, final List<URI> includeUris, final List<URI> omitUris) {
117        final StringJoiner preferJoin = new StringJoiner("; ");
118        preferJoin.add("return=" + prefer);
119
120        if (includeUris != null) {
121            final String include = includeUris.stream().map(URI::toString).collect(Collectors.joining(" "));
122            if (include.length() > 0) {
123                preferJoin.add("include=\"" + include + "\"");
124            }
125        }
126
127        if (omitUris != null) {
128            final String omit = omitUris.stream().map(URI::toString).collect(Collectors.joining(" "));
129            if (omit.length() > 0) {
130                preferJoin.add("omit=\"" + omit + "\"");
131            }
132        }
133
134        return preferJoin.toString();
135    }
136
137    /**
138     * Provide an etag for the if-none-match header for this request
139     *
140     * @param etag etag to provide as the if-none-match header
141     * @return this builder
142     */
143    public GetBuilder ifNoneMatch(final String etag) {
144        if (etag != null) {
145            request.setHeader(IF_NONE_MATCH, etag);
146        }
147        return this;
148    }
149
150    /**
151     * Provide a if-last-modified header for this request
152     *
153     * @param lastModified date to provided as the if-modified-since header
154     * @return this builder
155     */
156    public GetBuilder ifModifiedSince(final String lastModified) {
157        if (lastModified != null) {
158            request.setHeader(IF_MODIFIED_SINCE, lastModified);
159        }
160        return this;
161    }
162
163    @Override
164    public GetBuilder disableRedirects() {
165        return (GetBuilder) super.disableRedirects();
166    }
167
168    @Override
169    public GetBuilder wantDigest(final String value) {
170        return (GetBuilder) super.wantDigest(value);
171    }
172
173    @Override
174    public GetBuilder noCache() {
175        return (GetBuilder) super.noCache();
176    }
177
178    @Override
179    public GetBuilder acceptDatetime(final Instant acceptInstant) {
180        return (GetBuilder) super.acceptDatetime(acceptInstant);
181    }
182
183    @Override
184    public GetBuilder acceptDatetime(final String acceptDatetime) {
185        return (GetBuilder) super.acceptDatetime(acceptDatetime);
186    }
187
188    @Override
189    public GetBuilder addHeader(final String name, final String value) {
190        return (GetBuilder) super.addHeader(name, value);
191    }
192
193    @Override
194    public GetBuilder addLinkHeader(final FcrepoLink linkHeader) {
195        return (GetBuilder) super.addLinkHeader(linkHeader);
196    }
197}