<commit_before>package eu.freme.broker.eservices;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

import eu.freme.broker.exception.BadRequestException;
import eu.freme.broker.exception.InternalServerErrorException;
import eu.freme.broker.tools.NIFParameterSet;
import eu.freme.conversion.rdf.RDFConstants;
import eu.freme.conversion.rdf.RDFConstants.RDFSerialization;
import eu.freme.eservices.elink.DataEnricher;
import eu.freme.eservices.elink.Exporter;
import eu.freme.eservices.elink.Template;
import eu.freme.eservices.elink.TemplateDAO;
import eu.freme.broker.exception.TemplateNotFoundException;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONObject;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

@RestController
public class ELink extends BaseRestController {
    
        @Autowired
        DataEnricher dataEnricher;

        @Autowired
        TemplateDAO templateDAO;
        
        // Enriching using a template.        
        // POST /e-link/enrich/
        // Example: curl -X POST -d @data.ttl "http://localhost:8080/e-link/enrich/documents/?outformat=turtle&templateid=3&limit-val=4" -H "Content-Type: text/turtle"
	@RequestMapping(value = "/e-link/documents/", method = RequestMethod.POST)
	public ResponseEntity<String> enrich(
			@RequestParam(value = "templateid",    required=true)  int    templateId,
			@RequestHeader(value = "Accept",       required=false) String acceptHeader,
			@RequestHeader(value = "Content-Type", required=false) String contentTypeHeader,
                        @RequestBody String postBody,
                        @RequestParam Map<String,String> allParams) {
            try {
                String informat  = null;
                String f         = null;
                String outformat = null;
                String o         = null;
                
                HashMap<String, String> templateParams = new HashMap();
                
                for (Map.Entry<String, String> entry : allParams.entrySet()) {
                    switch(entry.getKey()) {
                        case "informat":
                            informat = entry.getValue();
                            break;
                        case "f":
                            f = entry.getValue();
                            break;
                        case "outformat":
                            outformat = entry.getValue();
                            break;
                        case "o":
                            o = entry.getValue();
                            break;
                        default:
                            templateParams.put(entry.getKey(), entry.getValue());
                            break;
                    }
                }
                
                // merge long and short parameters - long parameters override short parameters.
                if( informat == null ){
                    informat = f;
                }
                if( outformat == null ){
                    outformat = o;
                }
                
                if( postBody == null || postBody.trim().length() == 0 ){
                    throw new eu.freme.broker.exception.BadRequestException("No data to process could be found in the input.");
                }
                
                NIFParameterSet parameters = this.normalizeNif(postBody, informat, outformat, postBody, acceptHeader, contentTypeHeader, null);

                Model inModel = ModelFactory.createDefaultModel();
                
                switch(parameters.getInformat()) {
                    case TURTLE:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "TTL");
                        break;
                    case JSON_LD:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "JSON-LD");
                        break;
                    case RDF_XML:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "RDF/XML");
                        break;
                    case N_TRIPLES:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "N-TRIPLE");
                        break;
                    case N3:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "N3");
                        break;                        
                }
                
                inModel = dataEnricher.enrichNIF(inModel, templateId, templateParams);
                
                String serialization;
                switch(parameters.getOutformat()) {
                    case TURTLE:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.TURTLE);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);                
                    case JSON_LD:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.JSON_LD);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case RDF_XML:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.RDF_XML);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case N_TRIPLES:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.N_TRIPLES);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case N3:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.N3);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                }
            } catch (TemplateNotFoundException ex) {
                logger.warn("The template with the specified ID has not been found.", ex);
                throw new TemplateNotFoundException("The template with the specified ID has not been found.");
            } catch (Exception ex) {
                logger.error("Internal service problem. Please contact the service provider.", ex);
                throw new InternalServerErrorException("Unknown problem. Please contact us.");
            }
            throw new InternalServerErrorException("Unknown problem. Please contact us.");
	}
        
        // Creating a template.
        // POST /e-link/templates/
        // Example: curl -X POST -d @template.json "http://localhost:8080/e-link/templates/" -H "Content-Type: application/json" -H "Accept: application/json" -v
	@RequestMapping(value = "/e-link/templates/", method = RequestMethod.POST)
	public ResponseEntity<String> createTemplate(
			@RequestHeader(value = "Accept",       required=false) String acceptHeader,
			@RequestHeader(value = "Content-Type", required=false) String contentTypeHeader,
                        @RequestParam(value = "informat",      required=false) String informat,
                        @RequestParam(value = "f",             required=false) String f,
                        @RequestParam(value = "outformat",     required=false) String outformat,
                        @RequestParam(value = "o",             required=false) String o,
                        @RequestBody String postBody) {
            
            try {
                
                if( informat == null ){
                    informat = f;
                }
                if( outformat == null ){
                    outformat = o;
                }
            
                if( postBody == null || postBody.trim().length() == 0 ) {
                    return new ResponseEntity<String>("Empty body of the request.", HttpStatus.BAD_REQUEST);
                }
                
                // Checking the informat parameter
                RDFSerialization thisInformat;
                if (informat == null && contentTypeHeader == null) {
                    thisInformat = RDFSerialization.JSON;
		} else if (informat != null) {
                    if (!rdfELinkSerializationFormats.containsKey(informat)) {
                        throw new BadRequestException( "The parameter informat has invalid value \"" + informat + "\"");
                    }
                    thisInformat = rdfELinkSerializationFormats.get(informat);
		} else {
                    if (!rdfELinkSerializationFormats.containsKey(contentTypeHeader)) {
                        throw new BadRequestException("Content-Type header has invalid value \"" + contentTypeHeader + "\"");
                    }
                    thisInformat = rdfELinkSerializationFormats.get(contentTypeHeader);
		}
                // END: Checking the informat parameter
                
                // Checking the outformat parameter
                RDFSerialization thisOutformat;
		if( acceptHeader != null && acceptHeader.equals("*/*")) {
                    acceptHeader = "text/turtle";
		}
		if (outformat == null && acceptHeader == null) {
			thisOutformat = RDFSerialization.JSON;
		} else if (outformat != null) {
                    if (!rdfELinkSerializationFormats.containsKey(outformat)) {
                        throw new BadRequestException("Parameter outformat has invalid value \"" + outformat + "\"");
                    }
                    thisOutformat = rdfELinkSerializationFormats.get(outformat);
		} else {
                    if (!rdfELinkSerializationFormats.containsKey(acceptHeader)) {
			throw new BadRequestException("Parameter outformat has invalid value \"" + acceptHeader + "\"");
                    }
                    thisOutformat = rdfELinkSerializationFormats.get(acceptHeader);
		}
                // END: Checking the outformat parameter
                
                Template t = null;
                Model model = ModelFactory.createDefaultModel();
                
                switch(thisInformat) {
                    case JSON:
                        JSONObject jsonObj = new JSONObject(postBody);
                        t = new Template(templateDAO.generateTemplateId(), jsonObj.getString("endpoint"), jsonObj.getString("query"));
                        break;
                    case TURTLE:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "TTL");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        break;
                    case JSON_LD:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "JSON-LD");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        break;
                    case RDF_XML:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "RDF/XML");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        break;
                    case N_TRIPLES:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "N-Triples");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        break;
                    case N3:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "N3");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        break;                        
                }
                
                templateDAO.addTemplate(t);
                
                HttpHeaders responseHeaders = new HttpHeaders();
                URI location = new URI("/e-link/templates/"+t.getId());
                responseHeaders.setLocation(location);
                
                Model outModel;
                String serialization;
                
                switch(thisOutformat) {<commit_msg>fix for https://github.com/freme-project/e-Link/issues/14<commit_after>package eu.freme.broker.eservices;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;

import eu.freme.broker.exception.BadRequestException;
import eu.freme.broker.exception.InternalServerErrorException;
import eu.freme.broker.tools.NIFParameterSet;
import eu.freme.conversion.rdf.RDFConstants;
import eu.freme.conversion.rdf.RDFConstants.RDFSerialization;
import eu.freme.eservices.elink.DataEnricher;
import eu.freme.eservices.elink.Exporter;
import eu.freme.eservices.elink.Template;
import eu.freme.eservices.elink.TemplateDAO;
import eu.freme.broker.exception.TemplateNotFoundException;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONObject;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

@RestController
public class ELink extends BaseRestController {
    
        @Autowired
        DataEnricher dataEnricher;

        @Autowired
        TemplateDAO templateDAO;
        
        // Enriching using a template.        
        // POST /e-link/enrich/
        // Example: curl -X POST -d @data.ttl "http://localhost:8080/e-link/enrich/documents/?outformat=turtle&templateid=3&limit-val=4" -H "Content-Type: text/turtle"
	@RequestMapping(value = "/e-link/documents/", method = RequestMethod.POST)
	public ResponseEntity<String> enrich(
			@RequestParam(value = "templateid",    required=true)  int    templateId,
			@RequestHeader(value = "Accept",       required=false) String acceptHeader,
			@RequestHeader(value = "Content-Type", required=false) String contentTypeHeader,
                        @RequestBody String postBody,
                        @RequestParam Map<String,String> allParams) {
            try {
                String informat  = null;
                String f         = null;
                String outformat = null;
                String o         = null;
                
                HashMap<String, String> templateParams = new HashMap();
                
                for (Map.Entry<String, String> entry : allParams.entrySet()) {
                    switch(entry.getKey()) {
                        case "informat":
                            informat = entry.getValue();
                            break;
                        case "f":
                            f = entry.getValue();
                            break;
                        case "outformat":
                            outformat = entry.getValue();
                            break;
                        case "o":
                            o = entry.getValue();
                            break;
                        default:
                            templateParams.put(entry.getKey(), entry.getValue());
                            break;
                    }
                }
                
                // merge long and short parameters - long parameters override short parameters.
                if( informat == null ){
                    informat = f;
                }
                if( outformat == null ){
                    outformat = o;
                }
                
                if( postBody == null || postBody.trim().length() == 0 ){
                    throw new eu.freme.broker.exception.BadRequestException("No data to process could be found in the input.");
                }
                
                NIFParameterSet parameters = this.normalizeNif(postBody, informat, outformat, postBody, acceptHeader, contentTypeHeader, null);

                Model inModel = ModelFactory.createDefaultModel();
                
                switch(parameters.getInformat()) {
                    case TURTLE:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "TTL");
                        break;
                    case JSON_LD:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "JSON-LD");
                        break;
                    case RDF_XML:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "RDF/XML");
                        break;
                    case N_TRIPLES:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "N-TRIPLE");
                        break;
                    case N3:
                        inModel.read(new ByteArrayInputStream(postBody.getBytes()), null, "N3");
                        break;                        
                }
                
                inModel = dataEnricher.enrichNIF(inModel, templateId, templateParams);
                
                String serialization;
                switch(parameters.getOutformat()) {
                    case TURTLE:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.TURTLE);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);                
                    case JSON_LD:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.JSON_LD);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case RDF_XML:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.RDF_XML);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case N_TRIPLES:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.N_TRIPLES);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                    case N3:
                        serialization = rdfConversionService.serializeRDF(inModel, RDFSerialization.N3);
                        return new ResponseEntity<String>(serialization, HttpStatus.OK);
                }
            } catch (TemplateNotFoundException ex) {
                logger.warn("The template with the specified ID has not been found.", ex);
                throw new TemplateNotFoundException("The template with the specified ID has not been found.");
            } catch (Exception ex) {
                logger.error("Internal service problem. Please contact the service provider.", ex);
                throw new InternalServerErrorException("Unknown problem. Please contact us.");
            }
            throw new InternalServerErrorException("Unknown problem. Please contact us.");
	}
        
        // Creating a template.
        // POST /e-link/templates/
        // Example: curl -X POST -d @template.json "http://localhost:8080/e-link/templates/" -H "Content-Type: application/json" -H "Accept: application/json" -v
	@RequestMapping(value = "/e-link/templates/", method = RequestMethod.POST)
	public ResponseEntity<String> createTemplate(
			@RequestHeader(value = "Accept",       required=false) String acceptHeader,
			@RequestHeader(value = "Content-Type", required=false) String contentTypeHeader,
                        @RequestParam(value = "informat",      required=false) String informat,
                        @RequestParam(value = "f",             required=false) String f,
                        @RequestParam(value = "outformat",     required=false) String outformat,
                        @RequestParam(value = "o",             required=false) String o,
                        @RequestBody String postBody) {
            
            try {
                
                if( informat == null ){
                    informat = f;
                }
                if( outformat == null ){
                    outformat = o;
                }
            
                if( postBody == null || postBody.trim().length() == 0 ) {
                    return new ResponseEntity<String>("Empty body of the request.", HttpStatus.BAD_REQUEST);
                }
                
                // Checking the informat parameter
                RDFSerialization thisInformat;
                if (informat == null && contentTypeHeader == null) {
                    thisInformat = RDFSerialization.JSON;
		} else if (informat != null) {
                    if (!rdfELinkSerializationFormats.containsKey(informat)) {
                        throw new BadRequestException( "The parameter informat has invalid value \"" + informat + "\"");
                    }
                    thisInformat = rdfELinkSerializationFormats.get(informat);
		} else {
                    if (!rdfELinkSerializationFormats.containsKey(contentTypeHeader)) {
                        throw new BadRequestException("Content-Type header has invalid value \"" + contentTypeHeader + "\"");
                    }
                    thisInformat = rdfELinkSerializationFormats.get(contentTypeHeader);
		}
                // END: Checking the informat parameter
                
                // Checking the outformat parameter
                RDFSerialization thisOutformat;
		if( acceptHeader != null && acceptHeader.equals("*/*")) {
                    acceptHeader = "text/turtle";
		}
		if (outformat == null && acceptHeader == null) {
			thisOutformat = RDFSerialization.JSON;
		} else if (outformat != null) {
                    if (!rdfELinkSerializationFormats.containsKey(outformat)) {
                        throw new BadRequestException("Parameter outformat has invalid value \"" + outformat + "\"");
                    }
                    thisOutformat = rdfELinkSerializationFormats.get(outformat);
		} else {
                    if (!rdfELinkSerializationFormats.containsKey(acceptHeader)) {
			throw new BadRequestException("Parameter outformat has invalid value \"" + acceptHeader + "\"");
                    }
                    thisOutformat = rdfELinkSerializationFormats.get(acceptHeader);
		}
                // END: Checking the outformat parameter
                
                Template t = null;
                Model model = ModelFactory.createDefaultModel();
                
                switch(thisInformat) {
                    case JSON:
                        JSONObject jsonObj = new JSONObject(postBody);
                        t = new Template(templateDAO.generateTemplateId(), jsonObj.getString("endpoint"), jsonObj.getString("query"));
                        break;
                    case TURTLE:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "TTL");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        t.setId(templateDAO.generateTemplateId());
                        break;
                    case JSON_LD:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "JSON-LD");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        t.setId(templateDAO.generateTemplateId());
                        break;
                    case RDF_XML:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "RDF/XML");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        t.setId(templateDAO.generateTemplateId());
                        break;
                    case N_TRIPLES:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "N-Triples");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        t.setId(templateDAO.generateTemplateId());
                        break;
                    case N3:
                        model.read(new ByteArrayInputStream(postBody.getBytes()), null, "N3");
                        t = Exporter.getInstance().model2OneTemplate(model);
                        t.setId(templateDAO.generateTemplateId());
                        break;                        
                }
                
                templateDAO.addTemplate(t);
                
                HttpHeaders responseHeaders = new HttpHeaders();
                URI location = new URI("/e-link/templates/"+t.getId());
                responseHeaders.setLocation(location);
                
                Model outModel;
                String serialization;
                
                switch(thisOutformat) {
{'fraction_non_alphanumeric': 0.09032681251688081, 'fraction_numerical': 0.0018520662113670563, 'mean_word_length': 1.607182376018509, 'pattern_counts': {'":': 8, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2007332', 'n_tokens_mistral': 6299, 'n_tokens_neox': 5980, 'n_words': 1253}