/* * Copyright (C) 2012 Jan Pokorsky * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package cz.cas.lib.proarc.webapp.server.rest; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import cz.cas.lib.proarc.common.dao.Batch.State; import cz.cas.lib.proarc.common.dao.BatchView; import cz.cas.lib.proarc.common.dublincore.DcStreamEditor.DublinCoreRecord; import cz.cas.lib.proarc.common.dublincore.DcUtils; import cz.cas.lib.proarc.common.export.desa.DesaServices; import cz.cas.lib.proarc.common.fedora.SearchView.Item; import cz.cas.lib.proarc.common.json.JsonUtils; import cz.cas.lib.proarc.common.mods.ModsStreamEditor; import cz.cas.lib.proarc.common.mods.ModsUtils; import cz.cas.lib.proarc.common.object.DesDesaPlugin.DesMetadataHandler; import cz.cas.lib.proarc.common.object.DesDesaPlugin.DesObjectWrapper; import cz.cas.lib.proarc.common.object.ValueMap; import cz.cas.lib.proarc.common.object.emods.BdmArticleMapper.BdmModsWrapper; import cz.cas.lib.proarc.common.object.ndk.NdkMetadataHandler.ModsWrapper; import cz.cas.lib.proarc.desa.nomenclature.Nomenclatures; import cz.cas.lib.proarc.desa.nomenclature.Nomenclatures.RecCls; import cz.cas.lib.proarc.desa.nomenclature.Nomenclatures.RecCls.RecCl; import cz.cas.lib.proarc.mix.ImageCaptureMetadataType; import cz.cas.lib.proarc.mix.ImageCaptureMetadataType.ScannerCapture; import cz.cas.lib.proarc.mix.Mix; import cz.cas.lib.proarc.mix.MixType; import cz.cas.lib.proarc.mix.MixUtils; import cz.cas.lib.proarc.mods.IdentifierDefinition; import cz.cas.lib.proarc.mods.ModsDefinition; import cz.cas.lib.proarc.nsesss2.Dokument; import cz.cas.lib.proarc.nsesss2.NsesssUtils; import cz.cas.lib.proarc.nsesss2.Spis; import cz.cas.lib.proarc.nsesss2.TLogicky; import cz.cas.lib.proarc.nsesss2.TZpusobVyrizeni; import cz.cas.lib.proarc.oaidublincore.OaiDcType; import java.io.IOException; import java.io.StringWriter; import java.net.URL; import java.sql.Timestamp; import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.TimeZone; import javax.xml.bind.JAXB; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.transform.stream.StreamResult; import org.junit.After; import org.junit.AfterClass; import static org.junit.Assert.*; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * Test {@link JacksonProvider} configuration to comply with SmartGWT expectations. * * @author Jan Pokorsky */ public class JacksonProviderTest { public JacksonProviderTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testDublinCoreRecord() throws Exception { ObjectMapper om = new JacksonProvider().getContext(DublinCoreRecord.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); URL resource = JacksonProviderTest.class.getResource("dc_test.xml"); assertNotNull(resource); OaiDcType dc = JAXB.unmarshal(resource, OaiDcType.class); DublinCoreRecord dr = new DublinCoreRecord(dc, System.currentTimeMillis(), "uuid:1"); String toJson = om.writeValueAsString(dr); // System.out.println(toJson); DublinCoreRecord ndr = om.readValue(toJson, DublinCoreRecord.class); assertEquals(dr.getBatchId(), ndr.getBatchId()); assertEquals(dr.getPid(), ndr.getPid()); assertEquals(dr.getTimestamp(), ndr.getTimestamp()); assertEquals(dr.getDc().getIdentifiers(), ndr.getDc().getIdentifiers()); assertEquals(dr.getDc().getTitles(), ndr.getDc().getTitles()); assertEquals(dr.getDc().getCreators(), ndr.getDc().getCreators()); StringWriter toXml = new StringWriter(); DcUtils.marshal(new StreamResult(toXml), ndr.getDc(), true); toXml.flush(); // System.out.println("---"); // System.out.println(toXml); } @Test public void testMix() throws Exception { ObjectMapper om = new JacksonProvider().getContext(MixType.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); Mix mix = new Mix(); ScannerCapture scanner = new ScannerCapture(); scanner.setScannerManufacturer(MixUtils.stringType("ScannerManufacturer")); ImageCaptureMetadataType imageCaptureMetadata = new ImageCaptureMetadataType(); imageCaptureMetadata.setScannerCapture(scanner); mix.setImageCaptureMetadata(imageCaptureMetadata); String toJson = om.writeValueAsString(mix); // System.out.println(toJson); Mix result = om.readValue(toJson, Mix.class); assertNotNull(result); assertEquals("ScannerManufacturer", result.getImageCaptureMetadata().getScannerCapture().getScannerManufacturer().getValue()); // System.out.println(MixUtils.toXml(result, true)); } @Test public void testBdmModsDefinition() throws Exception { String toJson = "{\"BdmModsWrapper\":{\n" + " \"mods\":{\n" + " \"identifier\":{\n" + " \"value\":\"8232b78c-345b-40ae-9dc0-17bbb101d304\", \n" + " \"type\":\"uuid\"\n" + " }, \n" + " \"version\":\"3.5\", \n" + " \"relatedItem\":{\n" + " \"part\":{\n" + " \"extent\":{\n" + " \"start\":{\n" + " \"value\":\"1\"\n" + " }, \n" + " \"end\":{\n" + " \"value\":\"2\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }, \n" + " \"reviewed\":true\n" + "}}"; ObjectMapper om = new JacksonProvider().getContext(BdmModsWrapper.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); // System.out.println(toJson); BdmModsWrapper result = om.readValue(toJson, BdmModsWrapper.class); assertNotNull(result); ModsDefinition resultMods = result.getMods(); assertNotNull(resultMods); String toXml = ModsUtils.toXml(resultMods, true); IdentifierDefinition resultPid = resultMods.getIdentifier().get(0); assertEquals(toXml, "uuid", resultPid.getType()); assertEquals(toXml, "8232b78c-345b-40ae-9dc0-17bbb101d304", resultPid.getValue()); assertFalse(toXml, resultMods.getRelatedItem().isEmpty()); assertEquals(toXml, "1", resultMods.getRelatedItem().get(0).getPart().get(0).getExtent().get(0).getStart().getValue()); // System.out.println("---"); // System.out.println(toXml); } @Test public void testModsDefinition() throws Exception { ObjectMapper om = new JacksonProvider().getContext(ModsWrapper.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); ModsDefinition mods = ModsStreamEditor.defaultMods("uuid:test"); String toJson = om.writeValueAsString(new ModsWrapper(mods)); // System.out.println(toJson); ModsWrapper result = om.readValue(toJson, ModsWrapper.class); assertNotNull(result); ModsDefinition resultMods = result.getMods(); assertNotNull(resultMods); IdentifierDefinition resultPid = resultMods.getIdentifier().get(0); assertEquals("uuid", resultPid.getType()); assertEquals("test", resultPid.getValue()); // System.out.println("---"); // System.out.println(ModsUtils.toXml(resultMods, true)); } @Test public void testNsesss2WrappedInternalDocument() throws Exception { ObjectMapper om = new JacksonProvider().getContext(DesObjectWrapper.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); Dokument nsesss = NsesssUtils.defaultInternalDokument(); String toJson = om.writeValueAsString(new DesObjectWrapper(DesMetadataHandler.mapToJson(nsesss))); // System.out.println(toJson); DesObjectWrapper result = om.readValue(toJson, DesObjectWrapper.class); assertNotNull(result); assertNotNull(result.getDokument()); // System.out.println("---"); // System.out.println(NsesssUtils.toXml(result.getDokument(), true)); } @Test public void testNsesss2WrappedSpis() throws Exception { ObjectMapper om = new JacksonProvider().getContext(Spis.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); Spis spis = NsesssUtils.defaultSpis(); String toJson = om.writeValueAsString(new DesObjectWrapper(spis)); // System.out.println(toJson); DesObjectWrapper wrapper = om.readValue(toJson, DesObjectWrapper.class); assertNotNull(wrapper); Spis result = wrapper.getSpis(); assertNotNull(result); assertEquals("ERMS", result.getEvidencniUdaje().getEvidence().getNazevEvidenceDokumentu()); assertEquals(TZpusobVyrizeni.VYŘÍZENÍ_DOKUMENTEM, result.getEvidencniUdaje().getVyrizeniUzavreni().getZpusob()); assertEquals("Vyplývá ze spisového plánu organizace", result.getEvidencniUdaje().getVyrazovani().getSkartacniRezim().getOduvodneni()); assertEquals("Uzavření spisu", result.getEvidencniUdaje().getVyrazovani().getSkartacniRezim().getSpousteciUdalost()); assertEquals(TLogicky.ANO, result.getEvidencniUdaje().getManipulace().getAnalogovyDokument().ANO); // System.out.println("---"); // System.out.println(NsesssUtils.toXml(spisResult, true)); } @Test public void testReadNsesss2WrappedSpis() throws Exception { String toJson = "{ \"Spis\":{ \"EvidencniUdaje\":{ \"Identifikace\":{ \"Identifikator\":[ { \"value\":\"\", \"zdroj\":\"ERMS\" } ] }, \"Popis\":{ \"Nazev\":\"Název\", \"KlicovaSlova\":{ \"KlicoveSlovo\":[ \"slovo2\" ] } }, \"Evidence\":{ \"NazevEvidenceDokumentu\":\"ERMS\" }, \"Puvod\":{ \"DatumVytvoreni\":{ \"value\":\"2013-12-31T23:00:00.000+0000\" } }, \"VyrizeniUzavreni\":{ \"Zpusob\":\"vyřízení dokumentem\" }, \"Vyrazovani\":{ \"SkartacniRezim\":{ \"Oduvodneni\":\"Vyplývá ze spisového plánu organizace\", \"SkartacniLhuta\":1, \"SpousteciUdalost\":\"Uzavření spisu\" } }, \"Manipulace\":{ \"AnalogovyDokument\":\"ano\" } }, \"ID\":\"1\" }}"; ObjectMapper om = new JacksonProvider().getContext(DesObjectWrapper.class); // om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); DesObjectWrapper result = om.readValue(toJson, DesObjectWrapper.class); assertNotNull(result.getSpis()); } @Test public void testNomenclatureAsValueMap() throws Exception { Nomenclatures n = new Nomenclatures(); n.setRecCls(new RecCls()); List<RecCl> recCls = n.getRecCls().getRecCl(); RecCl recCl = new RecCl(); recCl.setFullyQcc("FullyQcc"); recCls.add(recCl); DesaServices desaServices = new DesaServices(null); List<ValueMap> valueMap = desaServices.getValueMap(n, "test"); SmartGwtResponse<ValueMap> sgr = new SmartGwtResponse<ValueMap>(valueMap); ObjectMapper om = new JacksonProvider().getContext(SmartGwtResponse.class); om.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); String toJson = om.writeValueAsString(sgr); // System.out.println(toJson); assertTrue(toJson.contains("\"data\":[{\"mapId\":\"test.rec-cl\",\"values\":[{\"fullyQcc\":\"FullyQcc\"}]}]}")); } /** * Tests read without mix in annotations and write with them. */ @Test public void testMapSearchViewItemToJson() throws Exception { String input = "{\"pid\":\"pid\",\"model\":\"model:test\",\"k0\":1}"; Item item = JsonUtils.createObjectMapper().readValue(input, Item.class); String json = toJson(item); // System.out.println(json); assertNotNull(json); } @Test public void testWrapRootValue() throws IOException { Record obj = new Record("value", null); String json = toJson(obj); assertTrue(json, json.startsWith("{\"record\":{")); } @Test public void testMapNonNullValues() throws IOException { Record obj = new Record("value", null); String json = toJson(obj); assertTrue(json, json.contains("\"field\":\"value\"")); assertFalse(json, json.contains("nullField")); } @Test public void testDateAsDateNotTimestamp() throws IOException { GregorianCalendar date = new GregorianCalendar(2012, 9, 30); date.setTimeZone(TimeZone.getTimeZone("GMT")); Record obj = new Record("value", null, date.getTime()); String json = toJson(obj); assertTrue(json, json.contains("\"dateField\":\"2012-10-30T00:00:00.000+0000\"")); } @Test public void testArray() throws IOException { ArrayHolder obj = new ArrayHolder(Arrays.asList( new Record("value[0]", null), new Record("value[1]", null) )); String json = toJson(obj); assertTrue(json, json.startsWith("{\"ArrayHolder\":{\"records\":[{\"field\":\"value[0]\"")); } /** * Default Jersey provider skips square brackets in case of single item array. * Jackson fixes it in default configuration. */ @Test public void testSingleItemArray() throws IOException { ArrayHolder obj = new ArrayHolder(Arrays.asList( new Record("value[0]", null) )); String json = toJson(obj); assertTrue(json, json.startsWith("{\"ArrayHolder\":{\"records\":[{\"field\":\"value[0]\"")); } @Test public void testMixedInAnnotations() throws Exception { BatchView b = new BatchView(); b.setCreate(Timestamp.valueOf("1991-01-19 00:00:01")); b.setFolder("folder/"); b.setId(1); b.setParentPid("parenPid"); b.setState(State.LOADED.name()); b.setTimestamp(new Timestamp(System.currentTimeMillis())); b.setTitle("title"); b.setUserId(10); b.setUserName("username"); String json = toJson(b); assertTrue(json, json.contains("\"description\":\"title\"")); assertTrue(json, json.contains("\"create\":\"1991-01")); assertFalse(json, json.contains("\"folder\":")); } private static String toJson(Object obj) throws IOException { ObjectMapper om = new JacksonProvider().getContext(obj == null ? null : obj.getClass()); return om.writeValueAsString(obj); } @XmlRootElement(name = "record") @XmlAccessorType(XmlAccessType.FIELD) static class Record { private String field; private String nullField; private Date dateField; public Record(String field, String nullField) { this(field, nullField, new Date()); } public Record(String field, String nullField, Date dateField) { this.field = field; this.nullField = nullField; this.dateField = dateField; } } @XmlAccessorType(XmlAccessType.FIELD) static class ArrayHolder { private List<Record> records; public ArrayHolder(List<Record> records) { this.records = records; } } }