Add quantity expressions in the backend
This commit is contained in:
parent
487547bd27
commit
1837926cb1
@ -185,6 +185,7 @@ public class QuickStatementsExporter implements WriterExporter {
|
|||||||
String unit = value.getUnit();
|
String unit = value.getUnit();
|
||||||
if (!unit.startsWith(unitPrefix))
|
if (!unit.startsWith(unitPrefix))
|
||||||
return null; // QuickStatements only accepts Qids as units
|
return null; // QuickStatements only accepts Qids as units
|
||||||
|
// TODO test this for values without bounds
|
||||||
String unitID = "U"+unit.substring(unitPrefix.length());
|
String unitID = "U"+unit.substring(unitPrefix.length());
|
||||||
return String.format(
|
return String.format(
|
||||||
Locale.US,
|
Locale.US,
|
||||||
|
@ -28,6 +28,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
|||||||
@Type(value = WbPropConstant.class, name = "wbpropconstant"),
|
@Type(value = WbPropConstant.class, name = "wbpropconstant"),
|
||||||
@Type(value = WbLanguageConstant.class, name = "wblanguageconstant"),
|
@Type(value = WbLanguageConstant.class, name = "wblanguageconstant"),
|
||||||
@Type(value = WbLanguageVariable.class, name = "wblanguagevariable"),
|
@Type(value = WbLanguageVariable.class, name = "wblanguagevariable"),
|
||||||
|
@Type(value = WbQuantityExpr.class, name="wbquantityexpr"),
|
||||||
})
|
})
|
||||||
public interface WbExpression<T> {
|
public interface WbExpression<T> {
|
||||||
|
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.openrefine.wikidata.schema;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException;
|
||||||
|
import org.wikidata.wdtk.datamodel.helpers.Datamodel;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.QuantityValue;
|
||||||
|
import org.wikidata.wdtk.datamodel.interfaces.StringValue;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
public class WbQuantityExpr implements WbExpression<QuantityValue> {
|
||||||
|
|
||||||
|
private final WbExpression<? extends StringValue> amountExpr;
|
||||||
|
private final WbExpression<? extends ItemIdValue> unitExpr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an expression for a quantity, which
|
||||||
|
* contains two sub-expressions: one for the amount (a string with
|
||||||
|
* a particular format) and one for the unit, which is optional.
|
||||||
|
*
|
||||||
|
* Setting unitExpr to null will give quantities without units. Setting
|
||||||
|
* it to a non-null value will make the unit mandatory: if the unit expression
|
||||||
|
* fails to evaluate, the whole quantity expression will fail too.
|
||||||
|
*/
|
||||||
|
@JsonCreator
|
||||||
|
public WbQuantityExpr(
|
||||||
|
@JsonProperty("amount") WbExpression<? extends StringValue> amountExpr,
|
||||||
|
@JsonProperty("unit") WbExpression<? extends ItemIdValue> unitExpr) {
|
||||||
|
Validate.notNull(amountExpr);
|
||||||
|
this.amountExpr = amountExpr;
|
||||||
|
this.unitExpr = unitExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QuantityValue evaluate(ExpressionContext ctxt)
|
||||||
|
throws SkipSchemaExpressionException {
|
||||||
|
StringValue amount = getLanguageExpr().evaluate(ctxt);
|
||||||
|
if (amount == null || amount.getString().isEmpty()) {
|
||||||
|
throw new SkipSchemaExpressionException();
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal parsedAmount = null;
|
||||||
|
try {
|
||||||
|
parsedAmount = new BigDecimal(amount.getString());
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
throw new SkipSchemaExpressionException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getUnitExpr() != null) {
|
||||||
|
ItemIdValue unit = getUnitExpr().evaluate(ctxt);
|
||||||
|
return Datamodel.makeQuantityValue(parsedAmount, unit.getIri());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Datamodel.makeQuantityValue(parsedAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("amount")
|
||||||
|
public WbExpression<? extends StringValue> getLanguageExpr() {
|
||||||
|
return amountExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("unit")
|
||||||
|
public WbExpression<? extends ItemIdValue> getUnitExpr() {
|
||||||
|
return unitExpr;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package org.openrefine.wikidata.schema;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.openrefine.wikidata.qa.QAWarningStore;
|
||||||
|
import org.openrefine.wikidata.schema.exceptions.SkipSchemaExpressionException;
|
||||||
|
import org.testng.Assert;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
import org.wikidata.wdtk.datamodel.helpers.Datamodel;
|
||||||
|
|
||||||
|
import com.google.refine.model.ModelException;
|
||||||
|
import com.google.refine.model.Project;
|
||||||
|
import com.google.refine.model.Row;
|
||||||
|
import com.google.refine.tests.RefineTest;
|
||||||
|
|
||||||
|
public class WbQuantityValueTest extends RefineTest {
|
||||||
|
|
||||||
|
protected Project project;
|
||||||
|
protected Row row;
|
||||||
|
protected ExpressionContext ctxt;
|
||||||
|
protected QAWarningStore warningStore;
|
||||||
|
|
||||||
|
@BeforeMethod
|
||||||
|
public void createProject() throws IOException, ModelException {
|
||||||
|
project = createCSVProject("Wikidata quantity value test project",
|
||||||
|
"column A\nrow1");
|
||||||
|
warningStore = new QAWarningStore();
|
||||||
|
row = project.rows.get(0);
|
||||||
|
ctxt = new ExpressionContext("http://www.wikidata.org/entity/", 0,
|
||||||
|
row, project.columnModel, warningStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithoutUnit() throws SkipSchemaExpressionException {
|
||||||
|
WbQuantityExpr expr = new WbQuantityExpr(new WbStringConstant("4.00"), null);
|
||||||
|
Assert.assertEquals(Datamodel.makeQuantityValue(new BigDecimal("4.00"), null, null, "1"), expr.evaluate(ctxt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = SkipSchemaExpressionException.class)
|
||||||
|
public void testInvalidAmountWithoutUnit() throws SkipSchemaExpressionException {
|
||||||
|
WbQuantityExpr expr = new WbQuantityExpr(new WbStringConstant("hello"), null);
|
||||||
|
expr.evaluate(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithUnit() throws SkipSchemaExpressionException {
|
||||||
|
WbItemConstant item = new WbItemConstant("Q42", "label");
|
||||||
|
WbQuantityExpr expr = new WbQuantityExpr(new WbStringConstant("56.094"), item);
|
||||||
|
Assert.assertEquals(Datamodel.makeQuantityValue(new BigDecimal("56.094"), null, null, "http://www.wikidata.org/entity/Q42"), expr.evaluate(ctxt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = SkipSchemaExpressionException.class)
|
||||||
|
public void testInvalidAmountWithUnit() throws SkipSchemaExpressionException {
|
||||||
|
WbItemConstant item = new WbItemConstant("Q42", "label");
|
||||||
|
WbQuantityExpr expr = new WbQuantityExpr(new WbStringConstant("invalid"), item);
|
||||||
|
expr.evaluate(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = SkipSchemaExpressionException.class)
|
||||||
|
public void testInvalidUnitWithAmount() throws SkipSchemaExpressionException {
|
||||||
|
WbItemVariable item = new WbItemVariable();
|
||||||
|
item.setColumnName("column A");
|
||||||
|
WbQuantityExpr expr = new WbQuantityExpr(new WbStringConstant("56.094"), item);
|
||||||
|
expr.evaluate(ctxt);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user