001    /***************************************************************************/
002    /*  Copyright (C) 2010-2011, Sebastian Hellmann                            */
003    /*  Note: If you need parts of NLP2RDF in another licence due to licence   */
004    /*  incompatibility, please mail hellmann@informatik.uni-leipzig.de        */
005    /*                                                                         */
006    /*  This file is part of NLP2RDF.                                          */
007    /*                                                                         */
008    /*  NLP2RDF is free software; you can redistribute it and/or modify        */
009    /*  it under the terms of the GNU General Public License as published by   */
010    /*  the Free Software Foundation; either version 3 of the License, or      */
011    /*  (at your option) any later version.                                    */
012    /*                                                                         */
013    /*  NLP2RDF is distributed in the hope that it will be useful,             */
014    /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
015    /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the           */
016    /*  GNU General Public License for more details.                           */
017    /*                                                                         */
018    /*  You should have received a copy of the GNU General Public License      */
019    /*  along with this program. If not, see <http://www.gnu.org/licenses/>.   */
020    /***************************************************************************/
021    
022    package org.nlp2rdf.webservice;
023    
024    import com.hp.hpl.jena.ontology.OntModel;
025    import com.hp.hpl.jena.ontology.OntModelSpec;
026    import com.hp.hpl.jena.rdf.model.ModelFactory;
027    import com.hp.hpl.jena.shared.JenaException;
028    import eu.lod2.nlp2rdf.schema.str.Document;
029    import org.apache.commons.lang.StringUtils;
030    import org.slf4j.Logger;
031    import org.slf4j.LoggerFactory;
032    
033    import javax.servlet.http.HttpServletRequest;
034    import java.io.ByteArrayInputStream;
035    import java.net.URLEncoder;
036    import java.security.InvalidParameterException;
037    import java.util.HashMap;
038    import java.util.List;
039    import java.util.Map;
040    
041    /**
042     * User: Sebastian Hellmann
043     * See    http://nlp2rdf.org/nif-1-0#toc-parameters
044     * A simple wrapper for the common options in NIF Services
045     * Almost fully implements
046     */
047    public class NIFParameters {
048        private static Logger log = LoggerFactory.getLogger(NIFParameters.class);
049    
050        //the plain text as is
051        private final String text;
052        //the RDF that was sent with the request
053        private final OntModel inputModel;
054        private final Map<String, String> parameterMap;
055    
056        private final String prefix;
057        private final String uriRecipe;
058        private final String format;
059    
060        //not in nif 1.0 diff or full
061        private final String output;
062    
063    
064        public NIFParameters(String text, String prefix, String output, String uriRecipe, String format, OntModel inputModel, Map<String, String> parameterMap) {
065            this.text = text;
066            this.prefix = prefix;
067            this.output = output;
068            this.uriRecipe = uriRecipe;
069            this.format = format;
070            this.inputModel = inputModel;
071            this.parameterMap = parameterMap;
072        }
073    
074    
075        /**
076         * Factory method
077         *
078         * @param httpServletRequest
079         * @return
080         */
081        public static NIFParameters getInstance(HttpServletRequest httpServletRequest) {
082            String requestUrl = httpServletRequest.getRequestURL().toString();
083            try {
084    
085                //required Parameter input-type
086                String input_type = requiredParameter("input-type", httpServletRequest, "text", "nif-owl");
087                String input = requiredParameter("input", httpServletRequest);
088    
089                //optional parameters
090                //note that nif=true is intentionally left out here, because it would be too late
091                String prefix = "http://nlp2rdf.lod2.eu/nif/";
092                String format = "rdfxml";
093                String urirecipe = "offset";
094                //this is not in the nif 1.0 spec
095                String output = "full";
096    
097                //the data variables
098                OntModel inputModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM, ModelFactory.createDefaultModel());
099                String text = null;
100    
101    
102                //prefix
103                if (isSet("prefix", httpServletRequest)) {
104                    prefix = httpServletRequest.getParameter("prefix");
105                }
106    
107                //format
108                if (isSet("format", httpServletRequest)) {
109                    format = requiredParameter("format", httpServletRequest, "rdfxml", "turtle", "json", "ntriples", "n3");
110                }
111    
112                //urirecipe
113                if (isSet("urirecipe", httpServletRequest)) {
114                    urirecipe = requiredParameter("urirecipe", httpServletRequest, "offset", "context-hash");
115                }
116    
117    
118                //output
119                if (isSet("output", httpServletRequest)) {
120                    output = requiredParameter("output", httpServletRequest, "full", "diff");
121                }
122    
123                //normalize input, i.e. fill the variables for text and model
124                if (input_type.equals("text")) {
125                    log.trace("Handling type text");
126                    // read the text
127                    text = httpServletRequest.getParameter("input");
128                    //make a NIF model to work on
129                    //URIGenerator uriGenerator = ModelHelper.determineGenerator(urirecipe);
130                    //inputModel = new Text2RDF().processAsDocument(prefix, text, new OpenNLPTokenizer(), uriGenerator);
131    
132                    /**********************
133                     * NOTE that parsing another NIF model is a little bit harder than just the output so this reference implementation is not yet complete.
134                     * *********************/
135                } else if (input_type.equals("nif-owl")) {
136                    // Read the model directly from the input
137    
138                    ByteArrayInputStream bais = new ByteArrayInputStream(httpServletRequest.getParameter("input").getBytes());
139                    try {
140                        inputModel.read(bais, "");
141                    } catch (JenaException e) {
142                        throw new InvalidParameterException("Jena could not read the presented nif-owl in RDF/XML format.\nFor the conversion of text \"input-type=text\" has to be set.");
143                    }
144                    //Validate
145                    List<Document> l = Document.list(inputModel);
146                    if (inputModel.isEmpty()) {
147                        throw new InvalidParameterException("The presented nif-owl representation must not be empty: no Document found. ");
148                    } else if (l.isEmpty()) {
149                        throw new InvalidParameterException("The presented nif-owl representation does not contain a document uri. ");
150                    }
151                    //TODO this is badly implemented, alternatively it could contain a sourceUrl
152                    if (!l.get(0).existsSourceString()) {
153                        throw new InvalidParameterException("The presented nif-owl representation does not contain a Document with a sourceString property.  ");
154                    }
155                    // read the text
156                    text = l.get(0).getSourceString();
157                }
158    
159                NIFParameters nifParameters = new NIFParameters(text, prefix, output, urirecipe, format, inputModel, copyParameterMap(httpServletRequest));
160                log.trace("created NIFParameters instance from " + input_type + ": " + nifParameters.toString());
161                return nifParameters;
162    
163            } catch (InvalidParameterException ipe) {
164                throw new InvalidParameterException(ipe.getMessage() + getDocumentation(requestUrl));
165            }
166        }
167    
168    
169        @Override
170        public String toString() {
171            return "NIFParameters{" +
172                    "text='" + text + '\'' +
173                    ", inputModel size=" + inputModel.size() +
174                    ", prefix='" + prefix + '\'' +
175                    ", uriRecipe='" + uriRecipe + '\'' +
176                    ", format='" + format + '\'' +
177                    ", output='" + output + '\'' +
178                    ", parameterMap=" + parameterMap +
179                    '}';
180        }
181    
182        public String getText() {
183            return text;
184        }
185    
186        public OntModel getInputModel() {
187            return inputModel;
188        }
189    
190        public Map<String, String> getParameterMap() {
191            return parameterMap;
192        }
193    
194        public String getPrefix() {
195            return prefix;
196        }
197    
198        public String getUriRecipe() {
199            return uriRecipe;
200        }
201    
202        public String getFormat() {
203            return format;
204        }
205    
206        public String getOutput() {
207            return output;
208        }
209    
210        public static String requiredParameter(String parameterName, HttpServletRequest hsr) {
211    
212            if (!isSet(parameterName, hsr)) {
213                throw new IllegalArgumentException("Missing parameter: " + parameterName + " is required. ");
214            }
215            return hsr.getParameter(parameterName);
216        }
217    
218        public static String requiredParameter(String parameterName, HttpServletRequest hsr, String... requiredValues) {
219            String value = requiredParameter(parameterName, hsr);
220            if (!oneOf(value, requiredValues)) {
221                throw new InvalidParameterException("Wrong value for parameter " + parameterName + ", value was: " + value + ", but must be one of ( " + StringUtils.join(requiredValues, ", ") + " ) ");
222            }
223            return value;
224        }
225    
226    
227        public static String getDocumentation(String serviceUrl) {
228            String doc = "";
229            try {
230                doc = "\nExample1: \n " + serviceUrl + "?input=" + URLEncoder.encode("That's a lot of nuts! That'll be four bucks, baby! You want fries with that? ", "UTF-8") + "&type=text";
231                doc += "\nExample2: \n " + serviceUrl + "?input=" + URLEncoder.encode("That's a lot of nuts! That's a lot of nuts! ", "UTF-8") + "&type=text";
232            } catch (Exception e) {
233                log.error("", e);
234            }
235            return doc;
236        }
237    
238        public static boolean oneOf(String value, String... possibleValues) {
239            for (String s : possibleValues) {
240                if (s.equals(value)) {
241                    return true;
242                }
243            }
244            return false;
245        }
246    
247        public static boolean isSet(String parameterName, HttpServletRequest hsr) {
248            boolean retVal = hsr.getParameterValues(parameterName) != null && hsr.getParameterValues(parameterName).length == 1 && hsr.getParameter(parameterName).length() > 0;
249            if (log.isTraceEnabled()) {
250                log.trace("Parameter " + parameterName + " isSet: " + retVal + " with value: " + hsr.getParameter(parameterName) + ")");
251            }
252            return retVal;
253        }
254    
255        public static Map<String, String> copyParameterMap(HttpServletRequest httpServletRequest) {
256            Map<String, String> ret = new HashMap<String, String>();
257            for (Object key : httpServletRequest.getParameterMap().keySet()) {
258                ret.put((String) key, httpServletRequest.getParameter((String) key));
259            }
260            return ret;
261        }
262    
263    }