/*******************************************************************************
* Copyright 2014 University of Southern California
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.kr2rml.template;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.digest.DigestUtils;
import edu.isi.karma.kr2rml.URIFormatter;
import edu.isi.karma.rep.Node;
import edu.isi.karma.rep.Row;
public class TemplateTermSetPopulator {
protected TemplateTermSet originalTerms;
private boolean URIify;
private boolean useNodeValue;
private StringBuilder baseTemplate;
private URIFormatter formatter;
// WK-226 Adds the ability to generate blank nodes with out satisfying any column terms
//TODO make this not static
private static Boolean noMinimumNumberOfSatisifiedTerms = false;
public TemplateTermSetPopulator(TemplateTermSet originalTerms, StringBuilder baseTemplate, URIFormatter formatter)
{
configure(originalTerms, baseTemplate, formatter);
this.URIify = true;
this.useNodeValue = true;
}
public TemplateTermSetPopulator(TemplateTermSet originalTerms, StringBuilder baseTemplate, URIFormatter formatter, boolean URIify, boolean useNodeValue)
{
configure(originalTerms, baseTemplate, formatter);
this.URIify = URIify;
this.useNodeValue = useNodeValue;
}
private void configure(TemplateTermSet originalTerms, StringBuilder baseTemplate, URIFormatter formatter)
{
this.originalTerms = originalTerms;
this.baseTemplate = baseTemplate;
this.formatter = formatter;
if(noMinimumNumberOfSatisifiedTerms == null)
{
// TODO look this up using the kr2ml configuration registry
noMinimumNumberOfSatisifiedTerms = false;
}
}
public TemplateTermSet getTerms()
{
return originalTerms;
}
public List<PopulatedTemplateTermSet> populate(Row topRow, TemplateTermSetPopulatorPlan plan)
{
List<PartiallyPopulatedTermSet> partials = plan.execute(topRow);
return generatePopulatedTemplatesFromPartials(partials);
}
public List<PopulatedTemplateTermSet> generatePopulatedTemplatesFromPartials(List<PartiallyPopulatedTermSet> partials)
{
return generatePopulatedTemplates(partials, baseTemplate, originalTerms.getAllTerms());
}
protected List<PopulatedTemplateTermSet> generatePopulatedTemplates(List<PartiallyPopulatedTermSet> partials, StringBuilder output,
List<TemplateTerm> terms) {
List<PopulatedTemplateTermSet> templates = new LinkedList<>();
for(PartiallyPopulatedTermSet partial : partials)
{
StringBuilder uri = new StringBuilder();
Map<ColumnTemplateTerm, Node> references = new HashMap<>();
boolean allTermsSatisifed = true;
boolean atLeastOneTermSatisified = false;
for(TemplateTerm term : terms)
{
if(term instanceof ColumnTemplateTerm)
{
Node n = partial.getValue((ColumnTemplateTerm)term);
if(n == null)
{
allTermsSatisifed = false;
continue;
}
if(n.getValue() == null || n.getValue().asString() == null || n.getValue().isEmptyValue() || n.getValue().asString().trim().isEmpty())
{
allTermsSatisifed = false;
}
else
{
atLeastOneTermSatisified = true;
}
references.put((ColumnTemplateTerm) term, n);
if(useNodeValue)
{
uri.append(n.getValue().asString());
}
else
{
uri.append("_");
String value = n.getValue().asString();
value = DigestUtils.shaHex(value);
uri.append(value);
uri.append("_" + n.getId());
}
}
else
{
uri.append(term.getTemplateTermValue());
}
}
if(areTermsSatisified(allTermsSatisifed, atLeastOneTermSatisified))
{
String value = uri.toString();
if(URIify)
{
value = formatter.getExpandedAndNormalizedUri(value);
}
templates.add(new PopulatedTemplateTermSet(originalTerms, references, value));
}
}
return templates;
}
private boolean areTermsSatisified(boolean termsSatisifed,
boolean atLeastOneTermSatisified) {
return termsSatisifed || (!useNodeValue && (atLeastOneTermSatisified || noMinimumNumberOfSatisifiedTerms));
}
//TODO make this workspace specific.
public static void setNoMinimumNumberOfSatisifiedTerms(boolean noMinimumNumberOfSatisifiedTerms)
{
TemplateTermSetPopulator.noMinimumNumberOfSatisifiedTerms = noMinimumNumberOfSatisifiedTerms;
}
}