package com.temenos.interaction.media.xhtml;
/*
* #%L
* interaction-media-xhtml
* %%
* Copyright (C) 2012 - 2013 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import org.junit.Assert;
import org.junit.Test;
import org.odata4j.core.OEntities;
import org.odata4j.core.OEntity;
import org.odata4j.core.OEntityKey;
import org.odata4j.core.OLink;
import org.odata4j.core.OProperties;
import org.odata4j.core.OProperty;
import org.odata4j.edm.EdmEntitySet;
import org.odata4j.edm.EdmEntityType;
import org.odata4j.edm.EdmProperty;
import org.odata4j.edm.EdmSimpleType;
import com.temenos.interaction.core.entity.Entity;
import com.temenos.interaction.core.entity.EntityMetadata;
import com.temenos.interaction.core.entity.EntityProperties;
import com.temenos.interaction.core.entity.EntityProperty;
import com.temenos.interaction.core.entity.GenericError;
import com.temenos.interaction.core.entity.Metadata;
import com.temenos.interaction.core.entity.vocabulary.Vocabulary;
import com.temenos.interaction.core.entity.vocabulary.terms.TermComplexGroup;
import com.temenos.interaction.core.entity.vocabulary.terms.TermComplexType;
import com.temenos.interaction.core.entity.vocabulary.terms.TermIdField;
import com.temenos.interaction.core.entity.vocabulary.terms.TermValueType;
import com.temenos.interaction.core.hypermedia.Link;
import com.temenos.interaction.core.resource.CollectionResource;
import com.temenos.interaction.core.resource.EntityResource;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.custommonkey.xmlunit.ComparisonController;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.custommonkey.xmlunit.DifferenceEngine;
import org.custommonkey.xmlunit.DifferenceListener;
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine;
import org.custommonkey.xmlunit.examples.MultiLevelElementNameAndTextQualifier;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
public class TestXHTMLProvider {
@Test
public void testWriteEntityResourceAcceptHTML() throws Exception {
EntityResource<Entity> er = new EntityResource<Entity>("Customer", createEntity("123", "Fred"));
List<Link> links = new ArrayList<Link>();
links.add(new Link(null, "Fred", "Self", "/Customer(123)", null, null, "GET", null));
er.setLinks(links);
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(er, EntityResource.class, Entity.class, null, MediaType.TEXT_HTML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("<li><a href=\"/Customer(123)\">Fred</a></li>"));
Assert.assertTrue(responseString.contains("WD8 1LK"));
Assert.assertTrue(responseString.contains("<td>hobbies</td><td><div contenteditable=\"true\">Tennis,Basketball,Swimming</div></td>"));
}
@Test
public void testWriteOEntityResourceAcceptHTML() throws Exception {
EntityResource<OEntity> er = createMockEntityResourceOEntity(createMockEdmEntitySet());
List<Link> links = new ArrayList<Link>();
links.add(new Link(null, "Fred", "Self", "/Customer(123)", null, null, "GET", null));
er.setLinks(links);
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(er, EntityResource.class, OEntity.class, null, MediaType.TEXT_HTML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("<li><a href=\"/Customer(123)\">Fred</a></li>"));
Assert.assertTrue(responseString.contains("<td>name</td><td><div contenteditable=\"true\">Fred</div></td>"));
}
@Test
public void testWriteEntityResourceAcceptXHTML() throws Exception {
EntityResource<Entity> er = new EntityResource<Entity>("Customer", createEntity("123", "Fred"));
List<Link> links = new ArrayList<Link>();
links.add(new Link(null, "Fred", "self", "/Customer(123)", null, null, "GET", null));
er.setLinks(links);
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(er, EntityResource.class, Entity.class, null, MediaType.APPLICATION_XHTML_XML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("<dd>WD8 1LK</dd>"));
Assert.assertTrue(responseString.contains("<ul><li><a href=\"/Customer(123)\" rel=\"self\">Fred</a></li></ul>"));
Assert.assertTrue(responseString.contains("<link rel=\"self\" href=\"/Customer(123)\">"));
}
@Test
public void testWriteCollectionResourceAcceptHTML() throws Exception {
Collection<EntityResource<Entity>> entities = new ArrayList<EntityResource<Entity>>();
entities.add(createEntityResource(createEntity("123", "Fred"), "123"));
entities.add(createEntityResource(createEntity("456", "Tom"), "456"));
entities.add(createEntityResource(createEntity("789", "Bob"), "789"));
CollectionResource<Entity> cr = new CollectionResource<Entity>("Customer", entities);
cr.setEntityName("Customer");
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(cr, CollectionResource.class, Entity.class, null, MediaType.TEXT_HTML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("Customer"));
Assert.assertTrue(responseString.contains("Tom"));
Assert.assertTrue(responseString.contains("navigate('/Customer(456)')"));
}
@Test
public void testWriteCollectionResourceAcceptXHTML() throws Exception {
Collection<EntityResource<Entity>> entities = new ArrayList<EntityResource<Entity>>();
entities.add(createEntityResource(createEntity("123", "Fred"), "123"));
entities.add(createEntityResource(createEntity("456", "Tom"), "456"));
entities.add(createEntityResource(createEntity("789", "Bob"), "789"));
CollectionResource<Entity> cr = new CollectionResource<Entity>("Customer", entities);
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(cr, CollectionResource.class, Entity.class, null, MediaType.APPLICATION_XHTML_XML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
XpathEngine engine = XMLUnit.newXpathEngine();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(false);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document responseDoc = db.parse(new InputSource(new StringReader(responseString)));
XPath xpath = XPathFactory.newInstance().newXPath();
// <li><dl><dt>id</dt><dd>123</dd><dt>address</dt><dl><dt>houseNumber</dt><dd>45</dd><dt>postcode</dt><dd>WD8 1LK</dd></dl><dt>name</dt><dd>Fred</dd><dt>hobbies</dt><dd>Tennis,Basketball,Swimming</dd></dl><ul><li><a href=\"/Customer(123)\" rel=\"self\">123</a></li></ul></li>"
// the simplest XPath getting us desired <li> element - only this one will have <dd> element equal to 123
String liNodeOfCustomer123XPath = "//li/dl[./dd=\"123\"]/dd[text()=\"Fred\"]";
Assert.assertNotNull(xpath.evaluate(liNodeOfCustomer123XPath, responseDoc, XPathConstants.NODE));
}
@Test
public void testWriteGenericErrorResourceAcceptHTML() throws Exception {
EntityResource<GenericError> er = createMockEntityResourceGenericError();
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(er, EntityResource.class, GenericError.class, null, MediaType.TEXT_HTML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("<div class=\"error\">[UPSTREAM_SERVER_UNAVAILABLE] Failed to connect to resource manager.</div>"));
}
@Test
public void testWriteGenericErrorResourceAcceptXHTML() throws Exception {
EntityResource<GenericError> er = createMockEntityResourceGenericError();
//Serialize metadata resource
XHTMLProvider p = new XHTMLProvider(createMockFlightMetadata());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
p.writeTo(er, EntityResource.class, GenericError.class, null, MediaType.APPLICATION_XHTML_XML_TYPE, null, bos);
String responseString = new String(bos.toByteArray(), "UTF-8");
Assert.assertTrue(responseString.contains("<error>[UPSTREAM_SERVER_UNAVAILABLE] Failed to connect to resource manager.</error>"));
}
private Metadata createMockFlightMetadata() {
//Define vocabulary for this entity
Metadata metadata = new Metadata("Customers");
EntityMetadata vocs = new EntityMetadata("Customer");
Vocabulary vocName = new Vocabulary();
vocName.setTerm(new TermComplexType(false));
vocName.setTerm(new TermIdField(true));
vocs.setPropertyVocabulary("name", vocName);
Vocabulary vocAddress = new Vocabulary();
vocAddress.setTerm(new TermComplexType(true));
vocs.setPropertyVocabulary("address", vocAddress);
Vocabulary vocNumbert = new Vocabulary();
vocNumbert.setTerm(new TermComplexGroup("address"));
vocNumbert.setTerm(new TermValueType(TermValueType.INTEGER_NUMBER));
vocs.setPropertyVocabulary("number", vocNumbert);
Vocabulary vocStreet = new Vocabulary();
vocStreet.setTerm(new TermComplexGroup("address"));
vocStreet.setTerm(new TermValueType(TermValueType.TEXT));
vocs.setPropertyVocabulary("street", vocStreet);
Vocabulary vocTown = new Vocabulary();
vocTown.setTerm(new TermComplexGroup("address"));
vocTown.setTerm(new TermValueType(TermValueType.TEXT));
vocs.setPropertyVocabulary("town", vocStreet);
Vocabulary vocPostCode = new Vocabulary();
vocPostCode.setTerm(new TermComplexGroup("address"));
vocPostCode.setTerm(new TermValueType(TermValueType.TEXT));
vocs.setPropertyVocabulary("postCode", vocPostCode);
Vocabulary vocDob = new Vocabulary();
vocDob.setTerm(new TermComplexType(false));
vocs.setPropertyVocabulary("dateOfBirth", vocDob);
Vocabulary vocSector = new Vocabulary();
vocSector.setTerm(new TermComplexType(false));
vocs.setPropertyVocabulary("sector", vocSector);
Vocabulary vocIndustry = new Vocabulary();
vocIndustry.setTerm(new TermComplexType(false));
vocs.setPropertyVocabulary("industry", vocIndustry);
Vocabulary vocHobbies = new Vocabulary();
vocHobbies.setTerm(new TermValueType(TermValueType.ENUMERATION));
vocs.setPropertyVocabulary("hobbies", vocHobbies);
metadata.setEntityMetadata(vocs);
return metadata;
}
private Entity createEntity(String id, String name) {
EntityProperties addressFields = new EntityProperties();
addressFields.setProperty(new EntityProperty("postcode", "WD8 1LK"));
addressFields.setProperty(new EntityProperty("houseNumber", "45"));
EntityProperties customerFields = new EntityProperties();
customerFields.setProperty(new EntityProperty("id", id));
customerFields.setProperty(new EntityProperty("name", name));
customerFields.setProperty(new EntityProperty("address", addressFields));
String[] hobbies = { "Tennis", "Basketball", "Swimming"};
customerFields.setProperty(new EntityProperty("hobbies", hobbies));
return new Entity("Customer", customerFields);
}
private EntityResource<Entity> createEntityResource(Entity entity, String id) {
EntityResource<Entity> entityResource = new EntityResource<Entity>(entity.getName(), entity);
Collection<Link> links = new ArrayList<Link>();
links.add(new Link(null, id, "self", "/" + entity.getName() + "(" + id + ")", null, null, "GET", null));
entityResource.setLinks(links);
return entityResource;
}
private EdmEntitySet createMockEdmEntitySet() {
// Create an entity set
List<EdmProperty.Builder> eprops = new ArrayList<EdmProperty.Builder>();
EdmProperty.Builder ep = EdmProperty.newBuilder("id").setType(EdmSimpleType.STRING);
eprops.add(ep);
EdmEntityType.Builder eet = EdmEntityType.newBuilder().setNamespace("InteractionTest").setName("Customer").addKeys(Arrays.asList("id")).addProperties(eprops);
EdmEntitySet.Builder eesb = EdmEntitySet.newBuilder().setName("Customer").setEntityType(eet);
return eesb.build();
}
private EntityResource<OEntity> createMockEntityResourceOEntity(EdmEntitySet ees) {
//Create an OEntity
OEntityKey entityKey = OEntityKey.create("123");
List<OProperty<?>> properties = new ArrayList<OProperty<?>>();
properties.add(OProperties.string("id", "123"));
properties.add(OProperties.string("name", "Fred"));
OEntity entity = OEntities.create(ees, entityKey, properties, new ArrayList<OLink>());
EntityResource<OEntity> er = new EntityResource<OEntity>("Customer", entity) {};
return er;
}
@SuppressWarnings("unchecked")
private EntityResource<GenericError> createMockEntityResourceGenericError() {
EntityResource<GenericError> er = mock(EntityResource.class);
GenericError error = new GenericError("UPSTREAM_SERVER_UNAVAILABLE", "Failed to connect to resource manager.");
when(er.getGenericEntity()).thenReturn(new GenericEntity<EntityResource<GenericError>>(er, er.getClass().getGenericSuperclass()));
when(er.getEntity()).thenReturn(error);
when(er.getEntityName()).thenReturn("Flight");
return er;
}
}