package de.tudresden.gis.manage.geooperators;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.io.InputStream;
import javax.faces.component.UIComponent;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.jsf.BaseActionListener;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.util.Val;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.util.FileManager;
/**
* The class implements the action listener for managing (add and remove) geooperators.
* The class is used to execute actions based on user input in backend section manage geooperators.
*
* @author Christin Henzen, Jochen Lenz
*
*/
public class GeooperatorController extends BaseActionListener {
private String geooperator = "";
private String definition = "";
private String scopeNote = "";
private String narrowMatch = "";
private String broadMatch = "";
private String closeMatch = "";
private String formalCategories = "";
private String geodataCategories = "";
private String geoinformaticsCategories = "";
private String legacyGISCategories = "";
private String pragmaticCategories = "";
private String technicalCategories = "";
private String parentgeooperator = "";
private String removegeooperator = "";
private SelectableGeooperators selectableGeooperators;
private String path = Thread.currentThread().getContextClassLoader().getResource("gpt/search/browse/browse-catalog.xml").getPath();
/**
* Constructor
*/
public GeooperatorController() {
super();
selectableGeooperators = new SelectableGeooperators();
selectableGeooperators.build();
}
//-- add geooperator ---------------------------------------
/**
* Method to get new geooperator name.
*
* @return geooperator
*/
public String getGeooperator() {
return geooperator;
}
/**
* Method to get new geooperator definition.
*
* @return definition
*/
public String getDefinition() {
return definition;
}
/**
* Method to get new geooperator scopeNote.
*
* @return scopeNote
*/
public String getScopeNote() {
return scopeNote;
}
/**
* Method to get new geooperator narrowMatch.
*
* @return narrowMatch
*/
public String getNarrowMatch() {
return narrowMatch;
}
/**
* Method to get new geooperator broadMatch.
*
* @return broadMatch
*/
public String getBroadMatch() {
return broadMatch;
}
/**
* Method to get new geooperator closeMatch.
*
* @return closeMatch
*/
public String getCloseMatch() {
return closeMatch;
}
/**
* Method to get new geooperator formalCategories.
*
* @return formalCategories
*/
public String getFormalCategories() {
return formalCategories;
}
/**
* Method to get new geooperator geodataCategories.
*
* @return geodataCategories
*/
public String getGeodataCategories() {
return geodataCategories;
}
/**
* Method to get new geooperator geoinformaticsCategories.
*
* @return geoinformaticsCategories
*/
public String getGeoinformaticsCategories() {
return geoinformaticsCategories;
}
/**
* Method to get new geooperator legacyGISCategories.
*
* @return legacyGISCategories
*/
public String getLegacyGISCategories() {
return legacyGISCategories;
}
/**
* Method to get new geooperator pragmaticCategories.
*
* @return pragmaticCategories
*/
public String getPragmaticCategories() {
return pragmaticCategories;
}
/**
* Method to get new geooperator technicalCategories.
*
* @return technicalCategories
*/
public String getTechnicalCategories() {
return technicalCategories;
}
/**
* Method to get chosen parent of new geooperator.
*
* @return parent geooperator name
*/
public String getParentgeooperator() {
return parentgeooperator;
}
/**
* Method to set new geooperator name.
*
* @param geooperator
*/
public void setGeooperator(String geooperator) {
this.geooperator = geooperator;
}
/**
* Method to set new geooperator definition.
*
* @param definition
*/
public void setDefinition(String definition) {
this.definition = definition;
}
/**
* Method to set new geooperator scopeNote.
*
* @param scopeNote
*/
public void setScopeNote(String scopeNote) {
this.scopeNote = scopeNote;
}
/**
* Method to set new geooperator narrowMatch.
*
* @param narrowMatch
*/
public void setNarrowMatch(String narrowMatch) {
this.narrowMatch = narrowMatch;
}
/**
* Method to set new geooperator broadMatch.
*
* @param broadMatch
*/
public void setBroadMatch(String broadMatch) {
this.broadMatch = broadMatch;
}
/**
* Method to set new geooperator closeMatch.
*
* @param closeMatch
*/
public void setCloseMatch(String closeMatch) {
this.closeMatch = closeMatch;
}
/**
* Method to set new geooperator formalCategories.
*
* @param formalCategories
*/
public void setFormalCategories(String formalCategories) {
this.formalCategories = formalCategories;
}
/**
* Method to set new geooperator geodataCategories.
*
* @param geodataCategories
*/
public void setGeodataCategories(String geodataCategories) {
this.geodataCategories = geodataCategories;
}
/**
* Method to set new geooperator geoinformaticsCategories.
*
* @param geoinformaticsCategories
*/
public void setGeoinformaticsCategories(String geoinformaticsCategories) {
this.geoinformaticsCategories = geoinformaticsCategories;
}
/**
* Method to set new geooperator legacyGISCategories.
*
* @param legacyGISCategories
*/
public void setLegacyGISCategories(String legacyGISCategories) {
this.legacyGISCategories = legacyGISCategories;
}
/**
* Method to set new geooperator pragmaticCategories.
*
* @param pragmaticCategories
*/
public void setPragmaticCategories(String pragmaticCategories) {
this.pragmaticCategories = pragmaticCategories;
}
/**
* Method to set new geooperator technicalCategories.
*
* @param technicalCategories
*/
public void setTechnicalCategories(String technicalCategories) {
this.technicalCategories = technicalCategories;
}
/**
* Method to set parent of new geooperator.
*
* @param parentgeooperator
*/
public void setParentgeooperator(String parentgeooperator) {
this.parentgeooperator = parentgeooperator;
}
//-- remove geooperator ---------------------------------------
/**
* Method to get chosen geooperator, which should be removed.
*
* @return geooperator name to be removed
*/
public String getRemovegeooperator() {
return removegeooperator;
}
/**
* Method to set chosen geooperator, which should be removed.
*
* @param removegeooperator
*/
public void setRemovegeooperator(String removegeooperator) {
this.removegeooperator = removegeooperator;
}
//------------------------------------------------------------
/**
* Method to get available geooperators.
*
* @return geooperators as @see SelectableGeooperators.
*/
public SelectableGeooperators getSelectableGeooperators() {
return selectableGeooperators;
}
/**
* Method get url conform label created from input field prefLabel
* @return label
* @throws UnsupportedEncodingException
*/
public String getLabel() throws UnsupportedEncodingException{
String label;
if (!geooperator.equals("0")){
label = geooperator.replaceAll(" ", "_");
label = URLEncoder.encode(label, "UTF-8");
} else {
label ="notSet";
}
return label;
}
@Override
/**
* Method to trigger add or remove scripts, based on user's action.
*/
protected void processSubAction(ActionEvent event, RequestContext context)
throws AbortProcessingException, Exception {
UIComponent component = event.getComponent();
String sCommand = Val.chkStr((String) component.getAttributes().get("submit"));
if (sCommand.equals("add")) {
// checkMandatoryFields();
addGeooperator();
//TODO: finish implementation, bug fix file location, ... and uncomment this.
// addRDF();
// addJSON();
} else {
removeGeooperator();
}
}
/**
* Method checks if mandatory fields in form are filled.
*/
private void checkMandatoryFields(){
if (geooperator.equals("0")){
throw new IllegalArgumentException( "Name of new geooperator is requierd." );
}
if (definition.equals("0")){
throw new IllegalArgumentException( "Definition of new geooperator is requierd." );
}
}
/**
* Method creates RDF model with values from form.
*
* @return Model
*/
private Model getRDFModel() throws UnsupportedEncodingException{
String nameSpace = "http://purl.org/net/jbrauner/geooperators#";
Model model = ModelFactory.createDefaultModel();
Resource description;
description = model.createResource( nameSpace + getLabel() );
if (!definition.equals("0")){
Property property_definition = model.createProperty( nameSpace, "definition" );
model.add (description, property_definition, ResourceFactory.createTypedLiteral(definition, XSDDatatype.XSDstring));
}
if (!geooperator.equals("0")){
Property property_prefLabel = model.createProperty( nameSpace, "prefLabel" );
model.add (description, property_prefLabel, ResourceFactory.createTypedLiteral(geooperator, XSDDatatype.XSDstring));
}
if (!scopeNote.equals("0")){
Property property_scopeNote = model.createProperty( nameSpace, "scopeNote" );
model.add (description, property_scopeNote, ResourceFactory.createTypedLiteral(scopeNote, XSDDatatype.XSDstring));
}
if (!narrowMatch.equals("0")){
Property property_narrowMatch = model.createProperty( nameSpace, "narrowMatch" );
Resource resource_narrowMatch = model.createResource( nameSpace + narrowMatch );
model.add( description, property_narrowMatch, resource_narrowMatch );
}
if (!broadMatch.equals("0")){
Property property_broadMatch = model.createProperty( nameSpace, "broadMatch" );
Resource resource_broadMatch = model.createResource( nameSpace + broadMatch );
model.add( description, property_broadMatch, resource_broadMatch );
}
if (!closeMatch.equals("0")){
Property property_closeMatch = model.createProperty( nameSpace, "closeMatch" );
Resource resource_closeMatch = model.createResource( nameSpace + closeMatch );
model.add( description, property_closeMatch, resource_closeMatch );
}
if (!formalCategories.equals("0")){
Property property_formalCategories = model.createProperty( nameSpace, "formalCategories" );
Resource resource_formalCategories = model.createResource( nameSpace + formalCategories );
model.add( description, property_formalCategories, resource_formalCategories );
}
if (!geodataCategories.equals("0")){
Property property_geodataCategories = model.createProperty( nameSpace, "geodataCategories" );
Resource resource_geodataCategories = model.createResource( nameSpace + geodataCategories );
model.add( description, property_geodataCategories, resource_geodataCategories );
}
if (!geoinformaticsCategories.equals("0")){
Property property_geoinformaticsCategories = model.createProperty( nameSpace, "geoinformaticsCategories" );
Resource resource_geoinformaticsCategories = model.createResource( nameSpace + geoinformaticsCategories );
model.add( description, property_geoinformaticsCategories, resource_geoinformaticsCategories );
}
if (!legacyGISCategories.equals("0")){
Property property_legacyGISCategories = model.createProperty( nameSpace, "legacyGISCategories" );
Resource resource_legacyGISCategories = model.createResource( nameSpace + legacyGISCategories );
model.add( description, property_legacyGISCategories, resource_legacyGISCategories );
}
if (!pragmaticCategories.equals("0")){
Property property_pragmaticCategories = model.createProperty( nameSpace, "pragmaticCategories" );
Resource resource_pragmaticCategories = model.createResource( nameSpace + pragmaticCategories );
model.add( description, property_pragmaticCategories, resource_pragmaticCategories );
}
if (!technicalCategories.equals("0")){
Property property_technicalCategories = model.createProperty( nameSpace, "technicalCategories" );
Resource resource_technicalCategories = model.createResource( nameSpace + technicalCategories );
model.add( description, property_technicalCategories, resource_technicalCategories );
}
model.setNsPrefix( "skos", nameSpace );
return model;
}
/**
* Method to create RDF file for geooperator.
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
*/
private void addRDF() throws FileNotFoundException, UnsupportedEncodingException {
String pathRDF = path.replaceAll("browse-catalog.xml", "geooperators.rdf");
Model model = ModelFactory.createDefaultModel();
InputStream in = FileManager.get().open( pathRDF );
if (in == null) {
Model model2 = getRDFModel();
FileOutputStream fout=new FileOutputStream(pathRDF);
model2.write(fout);
} else {
model.read(in, null);
Model model3 = getRDFModel();
Model model4 = model.union(model3);
FileOutputStream fout=new FileOutputStream(pathRDF);
model4.write(fout);
}
}
/**
* Method creates JSON Object with values from form.
*
* @return JSONObject
*/
private JSONObject getJSONObject() throws UnsupportedEncodingException{
JSONObject obj = new JSONObject();
obj.put("uri", "http://purl.org/net/jbrauner/geooperators#" + getLabel());
obj.put("definition", definition);
obj.put("label", getLabel());
obj.put("prefLabel", geooperator);
obj.put("scopeNote", scopeNote);
if (!narrowMatch.equals("0")){
JSONArray narrowMatchArray = new JSONArray();
narrowMatchArray.add(narrowMatch);
obj.put("narrowMatch", narrowMatchArray);
}
if (!broadMatch.equals("0")){
JSONArray broadMatchArray = new JSONArray();
broadMatchArray.add(broadMatch);
obj.put("broadMatch", broadMatchArray);
}
if (!closeMatch.equals("0")){
JSONArray closeMatchArray = new JSONArray();
closeMatchArray.add(closeMatch);
obj.put("closeMatch", closeMatchArray);
}
if (!narrowMatch.equals("0") && !broadMatch.equals("0")&& !closeMatch.equals("0")){
JSONArray relatedGeooperators = new JSONArray();
if (!narrowMatch.equals("0")){
relatedGeooperators.add(narrowMatch);
}
if (!broadMatch.equals("0")){
relatedGeooperators.add(broadMatch);
}
if (!closeMatch.equals("0")){
relatedGeooperators.add(closeMatch);
}
obj.put("relatedGeooperators", relatedGeooperators);
}
obj.put("type", "Concept");
if (!formalCategories.equals("0")){
JSONArray formalCategoriesArray = new JSONArray();
formalCategoriesArray.add(formalCategories);
obj.put("formalCategories", formalCategoriesArray);
}
if (!geodataCategories.equals("0")){
JSONArray geodataCategoriesArray = new JSONArray();
geodataCategoriesArray.add(geodataCategories);
obj.put("geodataCategories", geodataCategoriesArray);
}
if (!geoinformaticsCategories.equals("0")){
JSONArray geoinformaticsCategoriesArray = new JSONArray();
geoinformaticsCategoriesArray.add(geoinformaticsCategories);
obj.put("geoinformaticsCategories", geoinformaticsCategoriesArray);
}
if (!legacyGISCategories.equals("0")){
JSONArray legacyGISCategoriesArray = new JSONArray();
legacyGISCategoriesArray.add(legacyGISCategories);
obj.put("legacyGISCategories", legacyGISCategoriesArray);
}
if (!pragmaticCategories.equals("0")){
JSONArray pragmaticCategoriesArray = new JSONArray();
pragmaticCategoriesArray.add(pragmaticCategories);
obj.put("pragmaticCategories", pragmaticCategoriesArray);
}
if (!technicalCategories.equals("0")){
JSONArray technicalCategoriesArray = new JSONArray();
technicalCategoriesArray.add(technicalCategories);
obj.put("technicalCategories", technicalCategoriesArray);
}
return obj;
}
/**
* Method writes JSON File to harddisk.
*
* @param obj - JSON Object wich will be written inside the file.
* @param path - path on harddisk where file is written
*/
private void writeJSON(JSONObject obj, String path){
try {
FileWriter file = new FileWriter(path);
file.write(obj.toJSONString());
file.flush();
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Method to create JSON file for geooperator.
* @throws org.json.simple.parser.ParseException
* @throws UnsupportedEncodingException
*/
private void addJSON() throws org.json.simple.parser.ParseException, UnsupportedEncodingException {
JSONParser parser = new JSONParser();
String pathJSON = path.replaceAll("browse-catalog.xml", "geooperators.json");
try {
Object obj = parser.parse(new FileReader(pathJSON));
JSONObject jsonObject = (JSONObject) obj;
JSONObject jsonObject2 = getJSONObject();
JSONArray list = new JSONArray();
JSONArray items = (JSONArray) jsonObject.get("items");
Iterator<JSONObject> iterator = items.iterator();
while (iterator.hasNext()) {
list.add(iterator.next());
}
list.add(jsonObject2);
jsonObject.put("items", list);
writeJSON(jsonObject, pathJSON);
} catch (FileNotFoundException e) {
JSONObject jsonObject = new JSONObject();
JSONObject obj = getJSONObject();
JSONArray list = new JSONArray();
list.add(obj);
jsonObject.put("items", list);
writeJSON(jsonObject, pathJSON);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Method to add a geooperator to the geooperator registry, stored in a xml file.
* The registry is used to fill browse view in the appstore front end.
*/
private void addGeooperator() {
MessageBroker msgBroker = extractMessageBroker();
try {
File fXmlFile = new File(path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("item");
String[] addedGeoopArray = new String[1];
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
if (eElement.getElementsByTagName("id").item(0).getTextContent().equals(parentgeooperator)) {
Node geooperatorNode = createGeooperatorNode(doc, createGeooperatorId(geooperator), geooperator, "searchText=keywords:\"" + geooperator + "\"");
Node geooperatorImportNode = doc.importNode(geooperatorNode, true);
nNode.appendChild(geooperatorImportNode);
writeUpdatedXMLFile(doc, path);
addedGeoopArray[0] = geooperator;
}
}
}
if (addedGeoopArray[0] == null) {
Node geooperatorNode = createGeooperatorNode(doc, createGeooperatorId(geooperator), geooperator, "searchText=keywords:\"" + geooperator + "\"");
Node geooperatorImportNode = doc.importNode(geooperatorNode, true);
NodeList treeList = doc.getElementsByTagName("tree");
for (int temp = 0; temp < treeList.getLength(); temp++) {
Node nNode = treeList.item(temp);
nNode.appendChild(geooperatorImportNode);
writeUpdatedXMLFile(doc, path);
addedGeoopArray[0] = geooperator;
}
}
msgBroker.addSuccessMessage("catalog.publication.addGeooperator.success", addedGeoopArray);
} catch (Exception e) {
e.printStackTrace();
msgBroker.addErrorMessage("catalog.publication.addGeooperator.error");
}
}
/**
* Method to generate a random id for new geooperators.
* Geooperator registry requires unique id for each stored geooperator.
*
* @param geooperator
* @return id
*/
private String createGeooperatorId(String geooperator) {
String id = geooperator.replace(" ", "");
if (selectableGeooperators.getItems().contains(geooperator))
id = id + Math.random();
return id;
}
/**
* Method to generate a new geooperator node to insert in the geooperator registry file.
*
* @param doc - geooperator registry store file.
* @param id - id of new geooperator
* @param name - name of new geooperator
* @param query - query string: how to query process descriptions based on new geooperator
* @return xml node with information about new geooperator
*/
private Node createGeooperatorNode(Document doc, String id, String name, String query) {
Node item = doc.createElement("item");
Node idNode = doc.createElement("id");
Node idTextNode = doc.createTextNode(id);
Node idTextImportNode = doc.importNode(idTextNode, true);
idNode.appendChild(idTextImportNode);
Node idImportNode = doc.importNode(idNode, true);
item.appendChild(idImportNode);
Node nameNode = doc.createElement("name");
Node nameTextNode = doc.createTextNode(name);
Node nameTextImportNode = doc.importNode(nameTextNode, true);
nameNode.appendChild(nameTextImportNode);
Node nameImportNode = doc.importNode(nameNode, true);
item.appendChild(nameImportNode);
Node queryNode = doc.createElement("query");
Node queryTextNode = doc.createTextNode(query);
Node queryTextImportNode = doc.importNode(queryTextNode, true);
queryNode.appendChild(queryTextImportNode);
Node queryImportNode = doc.importNode(queryNode, true);
item.appendChild(queryImportNode);
return item;
}
/**
* Method to store updated geooperator registry.
*
* @param doc - updated list of geooperators as xml document
* @param path - path of geooperator registry xml document
*/
private void writeUpdatedXMLFile(Document doc, String path) {
try {
Source xmlSource = new DOMSource(doc);
Result result = new StreamResult(new FileOutputStream(path));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
transformer.transform(xmlSource, result);
}
catch (TransformerFactoryConfigurationError | TransformerException | IOException e) {
e.printStackTrace();
}
}
/**
* Method to remove a geooperator from the registry.
*/
private void removeGeooperator() {
MessageBroker msgBroker = extractMessageBroker();
try {
File fXmlFile = new File(path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("item");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
if (eElement.getElementsByTagName("id").item(0).getTextContent().equals(removegeooperator)) {
nNode.getParentNode().removeChild(nNode);
writeUpdatedXMLFile(doc, path);
}
}
}
msgBroker.addSuccessMessage("catalog.publication.removeGeooperator.success", new String[1]);
} catch (Exception e) {
e.printStackTrace();
msgBroker.addErrorMessage("catalog.publication.removeGeooperator.error");
}
}
}