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