package com.belladati.sdk.dataset.impl; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import java.io.IOException; import java.net.URISyntaxException; import java.util.Collections; import java.util.List; import org.apache.http.entity.StringEntity; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.yaml.snakeyaml.util.UriEncoder; import com.belladati.sdk.dataset.Attribute; import com.belladati.sdk.dataset.AttributeValue; import com.belladati.sdk.dataset.impl.AttributeImpl; import com.belladati.sdk.dataset.impl.AttributeValueImpl; import com.belladati.sdk.exception.impl.InvalidAttributeException; import com.belladati.sdk.exception.impl.InvalidAttributeValueException; import com.belladati.sdk.filter.FilterValue; import com.belladati.sdk.report.Report; import com.belladati.sdk.test.SDKTest; import com.belladati.sdk.test.TestRequestHandler; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @Test public class AttributesTest extends SDKTest { private final String reportsUri = "/api/reports"; private final String valuesUri = "/api/dataSets/%s/attributes/%s/values"; private final String imageUri = "/api/dataSets/%s/attributes/%s/%s/image"; private final String reportId = "123"; private final String dataSetId = "456"; private final String id = "id"; private final String name = "name"; private final String description = "report description"; private final String owner = "report owner"; private final String lastChange = "Mon, 16 Apr 2012 10:17:26 GMT"; private final String code = "code"; private final String type = "string"; private final String value1 = "Simple"; private final String value2 = "Some Spaces"; private final String value3 = "Test Characters /.,:;!@#$%^&*()_\\' End"; private final String value4 = "Chinese 把百度 And Latin ľščťžýáíéúäňô End"; /** No data set field means no attributes. */ public void reportWithoutDataSet() { ObjectNode node = builder.buildReportNode(reportId, name, description, owner, lastChange); node.remove("dataSet"); server.register(reportsUri + "/" + reportId, node.toString()); Report report = service.loadReport(reportId); assertEquals(report.getAttributes(), Collections.emptyList()); } /** No drilldownAttributes field means no attributes. */ public void reportWithoutDrilldownAttributes() { ObjectNode node = builder.buildReportNode(reportId, name, description, owner, lastChange); ((ObjectNode) node.get("dataSet")).remove("drilldownAttributes"); server.register(reportsUri + "/" + reportId, node.toString()); Report report = service.loadReport(reportId); assertEquals(report.getAttributes(), Collections.emptyList()); } /** drilldownAttributes field not an array means no attributes. */ public void reportWithNonArrayAttributes() { ObjectNode node = builder.buildReportNode(reportId, name, description, owner, lastChange); ((ObjectNode) node.get("dataSet")).put("drilldownAttributes", "not an array"); server.register(reportsUri + "/" + reportId, node.toString()); Report report = service.loadReport(reportId); assertEquals(report.getAttributes(), Collections.emptyList()); } /** Report attributes are loaded. */ public void reportWithAttribute() { String attId = "attribute id"; String attName = "attribute name"; String attCode = "attribute code"; ObjectNode node = builder.buildReportNode(reportId, name, description, owner, lastChange); ((ObjectNode) node.get("dataSet")).putAll(builder.buildDataSetNode(dataSetId, name, description, owner, lastChange)); ((ArrayNode) node.get("dataSet").get("drilldownAttributes")) .add(builder.buildAttributeNode(attId, attName, attCode, type)); server.register(reportsUri + "/" + reportId, node.toString()); Report report = service.loadReport(reportId); assertEquals(report.getAttributes().size(), 1); assertEquals(report.getAttributes().get(0).getName(), attName); assertEquals(report.getAttributes().get(0).getCode(), attCode); } /** Invalid attributes are ignored. */ @Test(dataProvider = "invalidAttributes") public void reportWithInvalidAttribute(JsonNode attribute) { ObjectNode node = builder.buildReportNode(reportId, name, description, owner, lastChange); ((ObjectNode) node.get("dataSet")).putAll(builder.buildDataSetNode(dataSetId, name, description, owner, lastChange)); ((ArrayNode) node.get("dataSet").get("drilldownAttributes")).add(attribute); server.register(reportsUri + "/" + reportId, node.toString()); Report report = service.loadReport(reportId); assertEquals(report.getAttributes(), Collections.emptyList()); } /** Missing values attribute means no attribute values. */ public void valuesWithoutValues() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); registerValues(new ObjectMapper().createObjectNode()); assertEquals(attribute.getValues().load().get(), Collections.emptyList()); } /** Null values attribute means no attribute values. */ public void valuesNull() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); registerValues(new ObjectMapper().createObjectNode().put("values", (String) null)); assertEquals(attribute.getValues().load().get(), Collections.emptyList()); } /** Values attribute not an array means no attribute values. */ public void valuesNotArray() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); registerValues(new ObjectMapper().createObjectNode().put("values", "not an array")); assertEquals(attribute.getValues().load().get(), Collections.emptyList()); } /** Values attribute empty means no attribute values. */ public void valuesEmpty() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); ObjectNode node = new ObjectMapper().createObjectNode(); node.put("values", new ObjectMapper().createArrayNode()); registerValues(node); assertEquals(attribute.getValues().load().get(), Collections.emptyList()); } /** Valid values are loaded from values attribute. */ public void valueValid() throws InvalidAttributeException { String label = "label"; String value = "value"; Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); ObjectNode node = new ObjectMapper().createObjectNode(); node.put("values", new ObjectMapper().createArrayNode().add(builder.buildAttributeValueNode(label, value))); registerValues(node); List<AttributeValue> values = attribute.getValues().load().get(); assertEquals(values.size(), 1); assertEquals(values.get(0).getLabel(), label); assertEquals(values.get(0).getValue(), value); assertEquals(attribute.toString(), name); assertEquals(values.get(0).toString(), label); } /** Invalid values in values attribute are ignored. */ @Test(dataProvider = "invalidValues") public void valueInvalid(JsonNode value) throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); ObjectNode node = new ObjectMapper().createObjectNode(); node.put("values", new ObjectMapper().createArrayNode().add(value)); registerValues(node); assertEquals(attribute.getValues().load().get(), Collections.emptyList()); } /** getValues() always returns the same object. */ public void cacheSame() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); assertSame(attribute.getValues(), attribute.getValues()); } /** * getAttributeValues() from service returns the same object as getValues() * from attribute. */ public void cacheFromServiceSame() throws InvalidAttributeException { Attribute attribute = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, name, code, type)); assertSame(service.getAttributeValues(dataSetId, code), attribute.getValues()); } /** equals and hashcode work as expected for attributes */ public void attributeEquality() throws InvalidAttributeException { Attribute att1 = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, "1", "1", type)); Attribute att2 = new AttributeImpl(service, dataSetId, builder.buildAttributeNode(id, "2", "2", type)); Attribute att3 = new AttributeImpl(service, dataSetId, builder.buildAttributeNode("other", "3", "3", type)); Attribute att4 = new AttributeImpl(service, "4", builder.buildAttributeNode(id, name, code, type)); assertEquals(att1, att2); assertEquals(att1.hashCode(), att2.hashCode()); assertNotEquals(att1, att3); assertEquals(att1, att4); assertFalse(att1.equals(new Object())); } /** equals and hashcode work as expected for attribute values */ public void attributeValueEquality() throws InvalidAttributeValueException { String value = "value"; AttributeValue v1 = new AttributeValueImpl(builder.buildAttributeValueNode("1", value)); AttributeValue v2 = new AttributeValueImpl(builder.buildAttributeValueNode("2", value)); AttributeValue v3 = new AttributeValueImpl(builder.buildAttributeValueNode("3", "3")); AttributeValue v4 = new FilterValue("4", value); assertEquals(v1, v2); assertEquals(v1, v4); assertEquals(v4, v1); assertEquals(v1.hashCode(), v2.hashCode()); assertEquals(v1.hashCode(), v4.hashCode()); assertFalse(v1.equals(new Object())); assertNotEquals(v1, v3); } /** Provides attribute JSON that's invalid in some way. */ @DataProvider(name = "invalidAttributes") protected Object[][] invalidAttributeProvider() { // invalid is if code or name is null or doesn't exist return new Object[][] { { builder.buildAttributeNode(null, name, code, type) }, { builder.buildAttributeNode(id, null, code, type) }, { builder.buildAttributeNode(id, name, null, type) }, { builder.buildAttributeNode(id, name, code, null) }, { builder.buildAttributeNode(id, name, code, type).retain("name", "code", "type") }, { builder.buildAttributeNode(id, name, code, type).retain("id", "code", "type") }, { builder.buildAttributeNode(id, name, code, type).retain("id", "name", "type") }, { builder.buildAttributeNode(id, name, code, type).retain("id", "name", "code") }, { builder.buildAttributeNode(id, name, code, "other_type") } }; } /** Provides attribute value JSON that's invalid in some way. */ @DataProvider(name = "invalidValues") protected Object[][] invalidValueProvider() { // invalid is if label or value is null or doesn't exist return new Object[][] { { builder.buildAttributeValueNode(null, "value") }, { builder.buildAttributeValueNode("label", null) }, { builder.buildAttributeValueNode("label", "value").retain("label") }, { builder.buildAttributeValueNode("label", "value").retain("value") } }; } /** * Tells the server to respond to an attribute value query with the given * JSON. */ private void registerValues(final JsonNode node) { server.register(String.format(valuesUri, dataSetId, code), new TestRequestHandler() { @Override protected void handle(HttpHolder holder) throws IOException { holder.response.setEntity(new StringEntity(node.toString())); } }); } @DataProvider(name = "postAttributeValueImage_provider") private Object[][] postAttributeValueImage_provider() { return new Object[][] { { value1 }, { value2 }, { value3 }, { value4 } }; } @Test(dataProvider = "postAttributeValueImage_provider") public void postAttributeValueImage(String value) throws URISyntaxException { String url = String.format(imageUri, dataSetId, code, UriEncoder.encode(value)); final boolean[] executed = new boolean[1]; server.register(url, new TestRequestHandler() { @Override protected void handle(HttpHolder holder) throws IOException { assertEquals(holder.getUrlParameters().size(), 0); holder.response.setEntity(new StringEntity("")); executed[0] = true; } }); service.postAttributeValueImage(dataSetId, code, value, getTestImageFile()); assertTrue(executed[0]); } }