WikibaseDateBOp.java
package org.wikidata.query.rdf.blazegraph.constraints;
import java.math.BigInteger;
import java.util.Map;
import org.wikidata.query.rdf.common.WikibaseDate;
import com.bigdata.rdf.internal.impl.literal.LiteralExtensionIV;
import com.bigdata.bop.BOp;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IValueExpression;
import com.bigdata.bop.NV;
import com.bigdata.rdf.error.SparqlTypeErrorException;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.XSD;
import com.bigdata.rdf.internal.constraints.DateBOp;
import com.bigdata.rdf.internal.constraints.DateBOp.DateOp;
import com.bigdata.rdf.internal.constraints.INeedsMaterialization;
import com.bigdata.rdf.internal.constraints.IVValueExpression;
import com.bigdata.rdf.internal.impl.literal.XSDIntegerIV;
import com.bigdata.rdf.model.BigdataLiteral;
import com.bigdata.rdf.sparql.ast.GlobalAnnotations;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* A date expression involving a left IValueExpression operand.
* The operation to be applied to the operands is specified by the {@link Annotations}
* annotation.
* @see com.bigdata.rdf.internal.constraints.DateBOp
* We are not extending com.bigdata.rdf.internal.constraints since get() is final there.
*/
public class WikibaseDateBOp extends IVValueExpression<IV> implements INeedsMaterialization {
/**
*
*/
@SuppressFBWarnings(
value = "IMC_IMMATURE_CLASS_BAD_SERIALVERSIONUID",
justification = "We need to keep serialVersionUID for blazegraph correctness sake.")
private static final long serialVersionUID = 9136864442064392445L;
/**
* Backup DateBOp for dates that aren't ours.
*/
private final DateBOp originalOp;
/**
*
* @param left The left operand.
* @param op The annotation specifying the operation to be performed on those operands.
*/
public WikibaseDateBOp(final IValueExpression<? extends IV> left,
final DateOp op, final GlobalAnnotations globals) {
this(new BOp[] {left}, anns(globals, new NV(DateBOp.Annotations.OP, op)));
}
/**
* Required shallow copy constructor.
*
* @param args
* The operands.
* @param anns
* The operation.
*/
public WikibaseDateBOp(final BOp[] args, Map<String, Object> anns) {
super(args, anns);
if (args.length != 1 || args[0] == null || getProperty(DateBOp.Annotations.OP) == null) {
throw new IllegalArgumentException();
}
originalOp = new DateBOp(args, anns);
}
/**
* Constructor required for {@link com.bigdata.bop.BOpUtility#deepCopy(BOp)}.
*/
public WikibaseDateBOp(final WikibaseDateBOp op) {
super(op);
originalOp = new DateBOp(op.originalOp);
}
/**
* Get Wikibase date from IV.
* @param iv
* @return Wikibase date object
*/
@SuppressWarnings("rawtypes")
private WikibaseDate getWikibaseDate(IV iv) {
if (iv instanceof LiteralExtensionIV) {
return WikibaseDate.fromSecondsSinceEpoch(((LiteralExtensionIV)iv).getDelegate().longValue());
}
try {
return WikibaseDate.fromString(iv.getValue().stringValue()).cleanWeirdStuff();
} catch (IllegalArgumentException e) {
return null;
}
}
/**
* Get expression value.
*/
@SuppressWarnings({"rawtypes", "checkstyle:cyclomaticcomplexity"})
public IV get(final IBindingSet bs) {
final IV left = left().get(bs);
// not yet bound?
if (left == null) {
throw new SparqlTypeErrorException.UnboundVarException();
}
if (left.isLiteral()) {
BigdataLiteral bl = (BigdataLiteral) left.getValue();
if (XSD.DATETIME.equals(bl.getDatatype())) {
final WikibaseDate date = getWikibaseDate(left);
if (date == null) {
throw new SparqlTypeErrorException();
}
switch (op()) {
case YEAR:
return new XSDIntegerIV(BigInteger.valueOf(date.year()));
case MONTH:
return new XSDIntegerIV(BigInteger.valueOf(date.month()));
case DAY:
return new XSDIntegerIV(BigInteger.valueOf(date.day()));
case HOURS:
return new XSDIntegerIV(BigInteger.valueOf(date.hour()));
case MINUTES:
return new XSDIntegerIV(BigInteger.valueOf(date.minute()));
case SECONDS:
return new XSDIntegerIV(BigInteger.valueOf(date.second()));
default:
throw new UnsupportedOperationException();
}
} else {
return originalOp.get(bs);
}
}
throw new SparqlTypeErrorException();
}
/**
* Get left operand.
*/
public IValueExpression<? extends IV> left() {
return get(0);
}
/**
* Get annotated operation.
*/
public DateOp op() {
return (DateOp) getRequiredProperty(DateBOp.Annotations.OP);
}
/**
* Convert to string.
*/
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(op());
sb.append('(').append(left()).append(')');
return sb.toString();
}
/**
* Materialization requirements.
*/
public Requirement getRequirement() {
return Requirement.SOMETIMES;
}
}