/**
* Copyright (c) 2013/2014 Verein zur Foerderung der IT-Sicherheit in Oesterreich (SBA).
* The work has been developed in the TIMBUS Project and the above-mentioned are Members of the TIMBUS Consortium.
* TIMBUS is supported by the European Union under the 7th Framework Programme for research and technological
* development and demonstration activities (FP7/2007-2013) under grant agreement no. 269940.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including without
* limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTIBITLY, or FITNESS FOR A PARTICULAR
* PURPOSE. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise,
* unless required by applicable law or agreed to in writing, shall any Contributor be liable for damages, including
* any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this
* License or out of the use or inability to use the Work.
* See the License for the specific language governing permissions and limitation under the License.
*/
package net.timbusproject.dpes.pi.kbserver.beans;
import ch.lambdaj.function.convert.Converter;
import com.hp.hpl.jena.query.QuerySolution;
import org.apache.commons.lang3.StringUtils;
import org.sba_research.timbus.kb.FormatMigrationOption;
import org.sba_research.timbus.kb.PackageKnowledgeBase;
import org.sba_research.timbus.kb.ToolKnowledgeBase;
import org.sba_research.timbus.kb.timbus.SameActionsStrategy;
import org.sba_research.timbus.kb.timbus.SameFreebaseGenreStrategy;
import org.sbaresearch.owl.JenaQueryFacade;
import org.sbaresearch.owl.OwlApiFacade;
import org.semanticweb.owlapi.model.IRI;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import static ch.lambdaj.Lambda.*;
import static org.hamcrest.Matchers.equalToIgnoringCase;
@ManagedBean
@SessionScoped
@SuppressWarnings("unused")
public class QueryBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(QueryBean.class);
public static final String ONTOLOGY_FILE_NAME = "/freebaseExtensions.owl";
private static final String kbPrefix = "http://timbus.teco.edu/ontologies/preservationIdentifier/toolKB_instance.owl#";
private static final String tplFormatInfo = "Format: %s\nPronom IDs: %s\n\n";
private static final String tplToolInfo = "Tool: %s\n\nActions:\n %s\n\nGenres:\n %s\n\n\n";
private static final String tplToolReplacement = "%s (using %s)\n\nsupports:\n%s\n\ngenres:\n%s\n\n\n";
private static final String tplPackageReplacement = "%s (both provide virtual Package(s) %s)\n";
private static final String tplPackageInfo= "%s provides Package(s) \n%s\n";
private static final String tplVirtualPackageInfo= "%s provided by Package(s) \n%s\n";
@ManagedProperty("#{knowledge}")
private KnowledgeBean knowledgeBean;
private ToolKnowledgeBase toolKnowledgeBase;
private JenaQueryFacade queryFacade;
private PackageKnowledgeBase packageKnowledgeBase;
private String queryString;
private String action;
private List<String> formatNames;
private List<String> toolNames;
private List<String> formatIDs;
private List<String> packageNames;
private List<String> virtualPackageNames;
private List<String> virtualPackageProvidedByFragments;
private List<String> queryResult = new ArrayList<>();
@PostConstruct
public void init() {
queryFacade = knowledgeBean.getQueryFacade();
toolKnowledgeBase = knowledgeBean.getToolKnowledgeBase();
packageKnowledgeBase = knowledgeBean.getPackageKnowledgeBase();
formatIDs = toolKnowledgeBase.getAllFormatIDs();
formatNames = getAllFormatNames();
toolNames = getAllToolNames();
packageNames = packageKnowledgeBase.getAllPackageNames();
virtualPackageNames = packageKnowledgeBase.getAllVirtualPackageNames();
virtualPackageProvidedByFragments = packageKnowledgeBase.getAllVirtualPackageProvidedByRelations();
Collections.sort(virtualPackageNames);
Collections.sort(formatNames);
Collections.sort(toolNames);
Collections.sort(packageNames);
Collections.sort(virtualPackageProvidedByFragments);
}
public void exec() {
if (action != null && !action.isEmpty()) {
try {
Method method = getClass().getDeclaredMethod(action);
method.invoke(this);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
notify("The provided action is not supported.");
}
}
}
public List<String> getQueryResult() {
return queryResult;
}
public void setQueryResult(List<String> queryResult) {
this.queryResult = queryResult;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public void setKnowledgeBean(KnowledgeBean knowledgeBean) {
this.knowledgeBean = knowledgeBean;
}
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public void toolReplacement() {
List<String> results = filter(equalToIgnoringCase(queryString), toolNames);
if (results.size() < 1) notify("Unable to find tool: " + queryString);
else if (results.size() > 1) notify("Multiple tools found: " + queryString);
else {
try {
queryResult = formatToolAlternatives(toolKnowledgeBase.getAlternativeTools(results.get(0)), SameActionsStrategy.class.getSimpleName());
queryResult.addAll(formatToolAlternatives(toolKnowledgeBase.getAlternativeTools(results.get(0), new SameFreebaseGenreStrategy()), SameFreebaseGenreStrategy.class.getSimpleName()));
} catch (Exception e) {
handleError(e);
}
}
}
private List<String> formatToolAlternatives(List<String> alternativeTools, final String strategy) {
return convert(alternativeTools, new Converter<String, String>() {
@Override
public String convert(String tool) {
return String.format(tplToolReplacement,
removeNamespace(tool),
strategy,
join(getActionsOfTool(removeNamespace(tool))),
join(toolKnowledgeBase.getGenresOfTool(removeNamespace(tool))));
}
});
}
public void packageReplacement() {
List<String> results = filter(equalToIgnoringCase(queryString), packageNames);
if (results.size() < 1)
notify("Unable to find package: " + queryString);
else if (results.size() > 1)
notify("Multiple packages found: " + queryString);
else {
try {
String packageName = results.get(0);
queryResult = formatPackageAlternatives(packageKnowledgeBase.getAlternativePackages(results.get(0)), packageName);
} catch (Exception e) {
handleError(e);
}
}
}
private List<String> formatPackageAlternatives(List<String> alternativePackages, final String replacedPackageName) {
return convert(alternativePackages, new Converter<String, String>() {
@Override
public String convert(String packageName) {
return String.format(tplPackageReplacement, removeNamespace(packageName),
join(packageKnowledgeBase.getProvidedVirtualPackages(removeNamespace(packageName), replacedPackageName), " | "));
}
});
}
private String join(List<String> items) {
return join(items, "\n");
}
private String join(List<String> items, String separator) {
String joined = StringUtils.join(items, separator);
return !joined.isEmpty() ? joined : "-";
}
private void handleError(Exception e) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Query Error", e.getMessage()));
queryResult = new ArrayList<>();
}
private void notify(String message) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Information", message));
queryResult = new ArrayList<>();
}
public void formatReplacementByID() {
List<String> results = filter(equalToIgnoringCase(queryString), formatIDs);
if (results.size() < 1) notify("Unable to find format: " + queryString);
else if (results.size() > 1) notify("Multiple formats found: " + queryString);
else {
try {
List<FormatMigrationOption> convertFromMigrationOptions = toolKnowledgeBase.getConvertFromMigrationOptions(results.get(0));
queryResult = JenaQueryFacade.removeNamespace(extract(convertFromMigrationOptions, on(FormatMigrationOption.class).getFormat()));
} catch (Exception e) {
handleError(e);
}
}
}
public void formatReplacement() {
List<String> results = filter(equalToIgnoringCase(queryString), formatNames);
results.addAll(filter(equalToIgnoringCase(queryString), formatIDs));
if (results.size() < 1) notify("Unable to find format: " + queryString);
else if (results.size() > 1) notify("Multiple formats found: " + queryString);
else {
try {
List<String> localFormatIDs = toolKnowledgeBase.getFormatIDs(kbPrefix + results.get(0));
localFormatIDs.addAll(filter(equalToIgnoringCase(queryString), formatIDs));
if (localFormatIDs.isEmpty()) notify("Unable to find Pronom ID for this format.");
else {
if (localFormatIDs.size() > 1) notify("Multiple Pronom IDs found for this format.");
queryResult = new ArrayList<>();
for (String formatID : localFormatIDs) {
queryResult.addAll(format(toolKnowledgeBase.getConvertFromMigrationOptions(formatID), "to"));
queryResult.addAll(format(toolKnowledgeBase.getConvertToMigrationOptions(formatID), "from"));
queryResult = removeDuplicates(queryResult);
}
}
} catch (Exception e) {
handleError(e);
}
}
}
private ArrayList<String> removeDuplicates(List<String> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
private List<String> format(List<FormatMigrationOption> convertFromMigrationOptions, final String prefix) {
return convert(convertFromMigrationOptions, new Converter<FormatMigrationOption, String>() {
@Override
public String convert(FormatMigrationOption migrationOption) {
return String.format("%s %s using %s", prefix, removeNamespace(migrationOption.getFormat()), removeNamespace(migrationOption.getTool()));
}
});
}
private String removeNamespace(String uri) {
return OwlApiFacade.getFragment(IRI.create(uri));
}
public void rawQuery() {
try {
List<QuerySolution> query = queryFacade.query(queryString);
queryResult = extract(query, on(QuerySolution.class).toString());
} catch (Exception e) {
handleError(e);
}
}
public List<String> completeQuery(String query) {
List<String> result = filter(new StartsWithIgnoringCaseFilter(query), formatNames);
result.addAll(filter(new StartsWithIgnoringCaseFilter(query), toolNames));
result.addAll(filter(new StartsWithIgnoringCaseFilter(query), formatIDs));
return result;
}
public List<String> completeQueryPackages(String query) {
List<String> result = filter(new StartsWithIgnoringCaseFilter(query), packageNames);
result.addAll(filter(new StartsWithIgnoringCaseFilter(query), virtualPackageNames));
result.addAll(filter(new StartsWithIgnoringCaseFilter(query), virtualPackageProvidedByFragments));
return result;
}
public void info() {
queryResult = new ArrayList<>();
try {
List<String> results = filter(equalToIgnoringCase(queryString), formatNames);
for (String format : results) {
queryResult.add(String.format(tplFormatInfo, format, StringUtils.join(toolKnowledgeBase.getFormatIDs(kbPrefix + format), ", ")));
}
results = filter(equalToIgnoringCase(queryString), formatIDs);
for (String format : results) {
for (String formatName : JenaQueryFacade.removeNamespace(toolKnowledgeBase.getFormatNames(format))) {
queryResult.add(String.format(tplFormatInfo, formatName, format));
}
}
results = filter(equalToIgnoringCase(queryString), toolNames);
for (String tool : results) {
queryResult.add(String.format(tplToolInfo, tool, join(getActionsOfTool(tool)), join(toolKnowledgeBase.getGenresOfTool(tool))));
}
} catch (Exception e) {
handleError(e);
}
}
public void infoPackages() {
queryResult = new ArrayList<>();
try {
List<String> results = filter(equalToIgnoringCase(queryString), packageNames);
for (String packageName : results) {
System.out.println("trying info for packageName " + packageName);
queryResult.add(String.format(tplPackageInfo, packageName, join(packageKnowledgeBase.getProvidedVirtualPackages(packageName))));
}
results = filter(equalToIgnoringCase(queryString), virtualPackageNames);
for (String virtualPackageName : results) {
System.out.println("trying info for virtualPackageName " + virtualPackageName);
queryResult.add(String.format(tplVirtualPackageInfo, virtualPackageName, join(packageKnowledgeBase.getProvidersOf(virtualPackageName))));
}
} catch (Exception e) {
handleError(e);
}
}
public List<String> getAllTools() {
return toolNames;
}
public List<String> getAllPackages() {
return packageNames;
}
public List<String> getAllVirtualPackages() {
return virtualPackageNames;
}
public List<String> getAllFormats() {
return formatNames;
}
// TODO: move to kblib
public List<String> getAllToolNames() {
String queryString = "" +
"PREFIX kb: <http://timbus.teco.edu/ontologies/preservationIdentifier/toolKB.owl#>\n" +
"\n" +
"SELECT ?tool\n" +
"{\n" +
" ?tool a kb:Tool .\n" +
"}\n" +
"GROUP BY ?tool";
return JenaQueryFacade.removeNamespace(JenaQueryFacade.extractColumn(queryFacade.query(queryString), "tool"));
}
// TODO: move to kblib
public List<String> getAllFormatNames() {
String queryString = "" +
"PREFIX kb: <http://timbus.teco.edu/ontologies/preservationIdentifier/toolKB.owl#>\n" +
"\n" +
"SELECT ?format\n" +
"{\n" +
" ?format a kb:FileFormat .\n" +
"}\n" +
"GROUP BY ?format";
return JenaQueryFacade.removeNamespace(JenaQueryFacade.extractColumn(queryFacade.query(queryString), "format"));
}
public List<String> getActionsOfTool(String tool) {
String queryString = "" +
"PREFIX kb: <http://timbus.teco.edu/ontologies/preservationIdentifier/toolKB.owl#>\n" +
"PREFIX kbi: <http://timbus.teco.edu/ontologies/preservationIdentifier/toolKB_instance.owl#>\n" +
"\n" +
"SELECT ?toolAction\n" +
"{\n" +
" kbi:" + tool + " kb:isProviding ?toolAction .\n" +
// " ?toolAction kb:isProviding ?action .\n" +
"}\n" +
"GROUP BY ?toolAction";
return JenaQueryFacade.removeNamespace(JenaQueryFacade.extractColumn(queryFacade.query(queryString), "toolAction"));
}
}