/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.json.metadata; import java.util.Set; import java.util.List; import java.util.Locale; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import org.opengis.metadata.citation.Party; import org.opengis.metadata.citation.Role; import org.opengis.metadata.citation.DateType; import org.apache.sis.metadata.MetadataStandard; import org.apache.sis.metadata.iso.DefaultMetadata; import org.apache.sis.metadata.iso.citation.DefaultCitation; import org.apache.sis.metadata.iso.citation.DefaultCitationDate; import org.apache.sis.metadata.iso.citation.DefaultIndividual; import org.apache.sis.metadata.iso.citation.DefaultOrganisation; import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty; import org.apache.sis.metadata.iso.extent.DefaultExtent; import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox; import org.apache.sis.metadata.iso.identification.DefaultDataIdentification; import org.apache.sis.metadata.iso.identification.DefaultKeywords; import org.apache.sis.util.CharSequences; import org.apache.sis.util.ComparisonMode; import org.junit.Test; import static org.junit.Assert.*; import static java.util.Arrays.asList; import static java.util.Collections.singleton; /** * Tests the {@link Template} class. * * @author Martin Desruisseaux (Geomatys) */ public final strictfp class TemplateTest { /** * Verifies the validity of templates returned by {@link Template#getInstance(String)}. * * @throws ParseException if a predefined template is not valid. */ @Test public void validateInstances() throws ParseException { final Set<String> names = Template.getAvailableNames(); assertTrue("profile_import", names.contains("profile_import")); assertTrue("profile_inspire_vector", names.contains("profile_inspire_vector")); assertTrue("profile_inspire_raster", names.contains("profile_inspire_raster")); assertTrue("profile_sensorml_component", names.contains("profile_sensorml_component")); assertTrue("profile_sensorml_system", names.contains("profile_sensorml_system")); for (final String name : names) { final Template template = Template.getInstance(name); assertNotNull(name, template); assertEquals(name, template.root.validatePath(null), template.depth); } } /** * Creates the metadata object corresponding to the test JSon string. */ private static DefaultMetadata createMetadata() { final DefaultCitation citation = new DefaultCitation("Data \"title\""); citation.setDates(singleton(new DefaultCitationDate(new Date(1272844800000L + 24*60*60*1000), DateType.CREATION))); final DefaultDataIdentification identification = new DefaultDataIdentification(); identification.setCitation(citation); identification.setExtents(singleton(new DefaultExtent(null, new DefaultGeographicBoundingBox(-11.4865013, -4.615912, 43.165467, 49.9990223), null, null) )); identification.setDescriptiveKeywords(asList( new DefaultKeywords("keyword 1", "keyword 2", "keyword 3"), new DefaultKeywords("keyword 4", "keyword 5") )); identification.setPointOfContacts(asList( responsibility(Role.AUTHOR, new DefaultIndividual ("An author", null, null)), responsibility(Role.COLLABORATOR, new DefaultIndividual ("A collaborator", null, null)), responsibility(Role.DISTRIBUTOR, new DefaultOrganisation("An organisation", null, null, null)) )); final DefaultMetadata metadata = new DefaultMetadata(); metadata.setFileIdentifier("An archive"); metadata.setLanguage(Locale.ENGLISH); metadata.setCharacterSets(Collections.singleton(StandardCharsets.UTF_16)); metadata.setMetadataStandardName("ISO19115"); metadata.setMetadataStandardVersion("2003/Cor.1:2006"); metadata.setIdentificationInfo(singleton(identification)); return metadata; } /** * Helper method for {@link #createMetadata()}. We need the deprecated {@link DefaultResponsibleParty} * instance because we need the legacy {@code organisationName} and {@code individualName} properties. */ @SuppressWarnings("deprecation") private static DefaultResponsibleParty responsibility(final Role role, final Party party) { final DefaultResponsibleParty r = new DefaultResponsibleParty(role); r.setParties(singleton(party)); return r; } /** * Returns a reader for the test resource of the given name. */ private static BufferedReader open(final String file) throws IOException { return new BufferedReader(new InputStreamReader(Template.class.getResourceAsStream(file), "UTF-8")); } /** * Returns all lines read from the test resource of the given name. */ static List<String> readAllLines(final String file) throws IOException { final List<String> lines = new ArrayList<>(); try (final BufferedReader in = open(file)) { String line; while ((line = in.readLine()) != null) { assertTrue(lines.add(line)); } } return lines; } /** * Asserts that a JSON output is equals to the expected one. * * @param expectedFile The filename (without directory) of the test resource containing the expected JSON content. * @param actual The JSON content produced by {@link Template}. * @throws IOException if an error occurred while reading the expected JSON file. */ static void assertJsonEquals(final String expectedFile, final CharSequence actual) throws IOException { int lineNumber = 0; final CharSequence[] lines = CharSequences.splitOnEOL(actual); try (final BufferedReader in = open(expectedFile)) { String expectedLine; while ((expectedLine = in.readLine()) != null) { final CharSequence actualLine = lines[lineNumber++]; if (!expectedLine.equals(actualLine)) { fail("Comparison failure at line " + lineNumber + ".\n" + "Expected: " + expectedLine + "\n" + "Actual: " + actualLine + '\n'); } } } } /** * Test writing of a simple metadata while pruning the empty nodes. * * @throws IOException if an error occurred while applying the template. */ @Test public void testWritePrune() throws IOException { final DefaultMetadata metadata = createMetadata(); final StringBuilder buffer = new StringBuilder(10000); Template.getInstance("profile_inspire_vector").write(metadata, buffer, true); assertJsonEquals("vector_prune.json", buffer); } /** * Test writing of a simple metadata without pruning the empty nodes. * * @throws IOException if an error occurred while applying the template. */ @Test public void testWriteFull() throws IOException { final DefaultMetadata metadata = createMetadata(); final StringBuilder buffer = new StringBuilder(40000); Template.getInstance("profile_inspire_vector").write(metadata, buffer, false); assertJsonEquals("vector_test.json", buffer); } /** * Tests {@link Template#read(Iterable, Object)} when storing in an initially empty {@link DefaultMetadata}. * * @throws IOException if an error occurred while reading the test JSON file. */ @Test public void testRead() throws IOException { /* * Get the expected metadata with only the first keyword of the first DescriptiveKeywords section. * This is because the JSON template restricts the first DescriptiveKeywords to only one keyword. * Also clear the geographic bouding box inclusion flag. */ final DefaultMetadata expected = createMetadata(); ((List<?>) expected.getIdentificationInfo().iterator().next() .getDescriptiveKeywords().iterator().next() .getKeywords()).subList(1, 3).clear(); ((DefaultGeographicBoundingBox) expected.getIdentificationInfo().iterator().next() .getExtents().iterator().next() .getGeographicElements().iterator().next()).setInclusion(null); /* * Parse and compare. */ final DefaultMetadata metadata = new DefaultMetadata(); Template.getInstance("profile_inspire_vector").read(readAllLines("vector_prune.json"), metadata, true); assertTrue(expected.equals(metadata, ComparisonMode.DEBUG)); } /** * Tests reading the un-pruned file. This test just ensures that no exception is thrown - we do not * yet verify the content. * * @throws IOException if an error occurred while reading the test JSON file. */ @Test public void testReadFull() throws IOException { final DefaultMetadata metadata = new DefaultMetadata(); Template.getInstance("profile_inspire_vector").read(readAllLines("vector_test.json"), metadata, false); assertFalse(metadata.isEmpty()); } /** * Tests with geographic elements of different types. * * @throws IOException if an error occurred while reading the test JSON file. */ @Test public void testGeographicElements() throws IOException { final List<String> lines = readAllLines("profile_dataset.json"); final Template template = new Template(MetadataStandard.ISO_19115, lines, null); final DefaultMetadata metadata = new DefaultMetadata(); template.read(lines, metadata, false); assertTrue(metadata.isEmpty()); } }