package ecologylab.bigsemantics.metametadata;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ecologylab.bigsemantics.collecting.SemanticsGlobalScope;
import ecologylab.bigsemantics.metametadata.fieldops.FieldOp;
import ecologylab.bigsemantics.metametadata.fieldops.FieldOpScope;
import ecologylab.net.ParsedURL;
import ecologylab.serialization.annotations.simpl_collection;
import ecologylab.serialization.annotations.simpl_nowrap;
import ecologylab.serialization.annotations.simpl_other_tags;
import ecologylab.serialization.annotations.simpl_scope;
/**
* Semantics that transforms locations, with operations such as set_param, strip_param inside it,
* for managing variability in Document location ParsedURL arguments.
*
* @author andruid
* @author quyin
*/
@simpl_other_tags("location_op")
public class FilterLocation
{
private static Logger logger = LoggerFactory.getLogger(FilterLocation.class);
@simpl_scope(FieldOpScope.NAME)
@simpl_nowrap
@simpl_collection
ArrayList<FieldOp> ops;
@simpl_nowrap
@simpl_collection("alternative_host")
ArrayList<String> alternativeHosts;
public ArrayList<FieldOp> getOps()
{
return ops;
}
public void setOps(ArrayList<FieldOp> ops)
{
this.ops = ops;
}
public void addOp(FieldOp op)
{
if (ops == null)
{
ops = new ArrayList<FieldOp>();
}
ops.add(op);
}
public ArrayList<String> getAlternativeHosts()
{
return alternativeHosts;
}
public void setAlternativeHosts(ArrayList<String> alternativeHosts)
{
this.alternativeHosts = alternativeHosts;
}
public void addAlternativeHost(String alternativeHost)
{
if (alternativeHosts == null)
{
alternativeHosts = new ArrayList<String>();
}
alternativeHosts.add(alternativeHost);
}
/**
* Filter the original location. If the original location is changed, return the new location, and
* put the original one in alternativeLocations.
*
* @param location
* The original location.
* @param alternativeLocations
* Locations with alternative domains.
* @return The filtered location.
* @throws Exception
*/
public ParsedURL filter(ParsedURL location, List<ParsedURL> alternativeLocations)
throws Exception
{
ParsedURL result = location;
if (location.isFile())
{
logger.warn("Not doing <filter_location> because this is a file: " + location);
}
else
{
Object opsResult = location;
if (ops != null && ops.size() > 0)
{
for (FieldOp op : ops)
{
opsResult = op.operateOn(opsResult);
}
}
result = (opsResult instanceof ParsedURL)
? ((ParsedURL) opsResult)
: ParsedURL.getAbsolute(opsResult.toString());
if (alternativeLocations == null)
{
// although we don't return the new list, this prevents from NPEs.
alternativeLocations = new ArrayList<ParsedURL>();
}
if (alternativeHosts != null)
{
final String origHost = result.host();
for (String alternativeHost : alternativeHosts)
{
if (!origHost.equals(alternativeHost))
{
ParsedURL newLocation = result.changeHost(alternativeHost);
if (!alternativeLocations.contains(newLocation))
{
alternativeLocations.add(newLocation);
}
}
}
}
if (result != location)
{
if (!alternativeLocations.contains(location))
{
alternativeLocations.add(location);
}
}
return result;
}
return location;
}
/**
* Filter the input Purl if needed, i.e. specified in the meta-metadata repository. It will first
* match the input Purl with a meta-metadata, and then use filtering rules for that meta-metadata
* to do filtering.
*
* @param location
* @param alternativeLocations
* @param semanticsScope
* @return
* @throws Exception
*/
public static ParsedURL filterIfNeeded(ParsedURL location,
List<ParsedURL> alternativeLocations,
SemanticsGlobalScope semanticsScope) throws Exception
{
MetaMetadata mm = semanticsScope.getMetaMetadataRepository().getDocumentMM(location);
FilterLocation filter = mm == null ? null : mm.getRewriteLocation();
if (filter != null)
{
ParsedURL filteredPurl = filter.filter(location, alternativeLocations);
return filteredPurl;
}
return location;
}
}