source: VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/de/uni_leipzig/asv/clarin/webservices/pidservices2/impl/PidWriterImpl.java @ 5498

Last change on this file since 5498 was 5498, checked in by Twan Goosen, 10 years ago

Updated PidWriterImpl?. Refs #596

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1package de.uni_leipzig.asv.clarin.webservices.pidservices2.impl;
2
3import java.util.Iterator;
4import java.util.Map;
5import java.util.regex.Matcher;
6import java.util.regex.Pattern;
7
8import net.sf.json.JSONArray;
9import net.sf.json.JSONObject;
10
11import org.apache.commons.httpclient.HttpException;
12import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
14
15import com.sun.jersey.api.client.Client;
16import com.sun.jersey.api.client.ClientHandlerException;
17import com.sun.jersey.api.client.ClientResponse;
18import com.sun.jersey.api.client.UniformInterfaceException;
19import com.sun.jersey.api.client.WebResource;
20import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
21
22import de.uni_leipzig.asv.clarin.webservices.pidservices2.Configuration;
23import de.uni_leipzig.asv.clarin.webservices.pidservices2.HandleField;
24import de.uni_leipzig.asv.clarin.webservices.pidservices2.interfaces.PidWriter;
25
26/**
27 * Registering new handles at handle server or modifying existing PID entries
28 *
29 * @author Thomas Eckart
30 * @author Twan Goosen
31 */
32public class PidWriterImpl implements PidWriter {
33
34    private final static Logger LOG = LoggerFactory.getLogger(PidWriterImpl.class);
35    public static final Pattern PID_INPUT_PATTERN = Pattern.compile("^[0-9A-z-]+$");
36    private static final Pattern PID_OUTPUT_PATTERN = Pattern.compile(".*location</dt><dd><a href=\"([0-9A-z-]+)\">.*");
37
38    /**
39     *
40     * @param configuration
41     * @param fieldMap
42     * @param pid PID to be created, must match {@link #PID_INPUT_PATTERN}
43     * @return
44     * @throws HttpException if the PID could not be created, for instance
45     * because the requested PID already exists
46     * @throws IllegalArgumentException if the provided PID does not match
47     * {@link #PID_INPUT_PATTERN}
48     */
49    @Override
50    public String registerNewPID(final Configuration configuration, Map<HandleField, String> fieldMap, String pid)
51            throws HttpException, IllegalArgumentException {
52        LOG.debug("Try to create handle {} at {} with values: {}", pid, configuration.getServiceBaseURL(), fieldMap);
53
54        // validate the requested PID
55        if (!PID_INPUT_PATTERN.matcher(pid).matches()) {
56            throw new IllegalArgumentException(pid);
57        }
58
59        // adding the PID to the request URL
60        final String baseUrl = String.format("%s%s/%s",
61                configuration.getServiceBaseURL(), configuration.getHandlePrefix(), pid);
62        final WebResource.Builder resourceBuilder = createResourceBuilderForNewPID(configuration, baseUrl);
63
64        final JSONArray jsonArray = createJSONArray(fieldMap);
65        final ClientResponse response = resourceBuilder
66                // this header will tell the server to fail if the requested PID already exists
67                .header("If-None-Match", "*")
68                // PUT the handle at the specified location
69                .put(ClientResponse.class, jsonArray.toString());
70        return processCreateResponse(response, configuration);
71    }
72
73    @Override
74    public String registerNewPID(final Configuration configuration, Map<HandleField, String> fieldMap)
75            throws HttpException {
76        LOG.debug("Try to create handle at {} with values: {}", configuration.getServiceBaseURL(), fieldMap);
77
78        final String baseUrl = configuration.getServiceBaseURL() + configuration.getHandlePrefix();
79        final WebResource.Builder resourceBuilder = createResourceBuilderForNewPID(configuration, baseUrl);
80
81        final JSONArray jsonArray = createJSONArray(fieldMap);
82        final ClientResponse response = resourceBuilder
83                // POST the new handle definition to the handles resource
84                .post(ClientResponse.class, jsonArray.toString());
85        return processCreateResponse(response, configuration);
86    }
87
88    private WebResource.Builder createResourceBuilderForNewPID(final Configuration configuration, final String baseUrl) {
89        final Client client = Client.create();
90        client.addFilter(new HTTPBasicAuthFilter(configuration.getUser(), configuration.getPassword()));
91        // TODO: request JSON ("application/json") as soon as GWDG respects that accept header
92        final WebResource.Builder resourceBuilder = client.resource(baseUrl).accept("application/xhtml+xml").type("application/json");
93        return resourceBuilder;
94    }
95
96    private String processCreateResponse(final ClientResponse response, final Configuration configuration) throws HttpException, UniformInterfaceException, RuntimeException, ClientHandlerException {
97        if (response.getStatus() != 201) {
98            throw new HttpException("" + response.getStatus());
99        }
100
101        // TODO CHANGE this to JSON processing ASAP, when GWDG respects accept header
102        String responseString = response.getEntity(String.class).trim().replaceAll("\n", "");
103        Matcher matcher = PID_OUTPUT_PATTERN.matcher(responseString);
104        if (matcher.matches()) {
105            return configuration.getHandlePrefix() + "/" + matcher.group(1);
106        } else {
107            LOG.error("No PID found in response string: {}", responseString);
108            throw new RuntimeException("Unparsable response from " + configuration.getServiceBaseURL());
109        }
110    }
111
112    @Override
113    public void modifyPid(final Configuration configuration, final String pid, Map<HandleField, String> fieldMap) {
114        LOG.debug("Try to modify handle \"" + pid + "\" at " + configuration.getServiceBaseURL() + " with new values: "
115                + fieldMap);
116
117        final Client client = Client.create();
118        client.addFilter(new HTTPBasicAuthFilter(configuration.getUser(), configuration.getPassword()));
119        final WebResource webResource = client.resource(configuration.getServiceBaseURL() + pid);
120
121        JSONArray jsonArray = createJSONArray(fieldMap);
122        webResource.accept("application/json").type("application/json").put(ClientResponse.class, jsonArray.toString());
123    }
124
125    /**
126     * Generates JSON array that is understood by the EPIC handle service
127     *
128     * @param fieldMap mapping handle field -> value
129     * @return JSON array
130     */
131    private JSONArray createJSONArray(Map<HandleField, String> fieldMap) {
132        JSONArray jsonArray = new JSONArray();
133        JSONObject jsonObject;
134
135        Iterator<HandleField> fieldIter = fieldMap.keySet().iterator();
136        while (fieldIter.hasNext()) {
137            jsonObject = new JSONObject();
138            HandleField handleFieldTyp = fieldIter.next();
139            jsonObject.put("type", handleFieldTyp);
140            jsonObject.put("parsed_data", fieldMap.get(handleFieldTyp));
141            jsonArray.add(jsonObject);
142        }
143
144        return jsonArray;
145    }
146}
Note: See TracBrowser for help on using the repository browser.