blob: a85ef325a39a0e899cc9a95a37dee7e49ed9f6f8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.sis.metadata;
import java.util.Arrays;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Role;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.citation.ResponsibleParty;
import org.opengis.metadata.acquisition.Instrument;
import org.opengis.metadata.acquisition.Platform;
import org.apache.sis.util.iso.SimpleInternationalString;
import org.apache.sis.metadata.iso.DefaultIdentifier;
import org.apache.sis.metadata.iso.citation.DefaultCitation;
import org.apache.sis.metadata.iso.citation.DefaultIndividual;
import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
import org.apache.sis.metadata.iso.acquisition.DefaultInstrument;
import org.apache.sis.metadata.iso.acquisition.DefaultPlatform;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
import org.junit.Test;
import static java.util.Collections.singleton;
import static org.junit.Assert.*;
/**
* Tests the {@link HashCode} class. This is also used as a relatively simple {@link MetadataVisitor} test.
* The entry point is the {@link HashCode#walk(MetadataStandard, Class, Object, boolean)} method.
*
*
* @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 1.0
* @module
*/
@DependsOn(PropertyAccessorTest.class)
public final strictfp class HashCodeTest extends TestCase {
/**
* Computes the hash code value of the given object.
*/
private static Integer hash(final Object metadata) {
return HashCode.getOrCreate().walk(MetadataStandard.ISO_19115, null, metadata, true);
}
/**
* Tests hash code computation of an object that do not contain other metadata.
*/
@Test
public void testSimple() {
final DefaultCitation instance = new DefaultCitation();
final int baseCode = Citation.class.hashCode();
assertEquals("Empty metadata.", Integer.valueOf(baseCode), hash(instance));
final InternationalString title = new SimpleInternationalString("Some title");
instance.setTitle(title);
assertEquals("Metadata with a single value.", Integer.valueOf(baseCode + title.hashCode()), hash(instance));
final InternationalString alternateTitle = new SimpleInternationalString("An other title");
instance.setAlternateTitles(singleton(alternateTitle));
assertEquals("Metadata with two values.",
Integer.valueOf(baseCode + title.hashCode() + Arrays.asList(alternateTitle).hashCode()),
hash(instance));
}
/**
* Tests hash code computation of an object containing another metadata object.
*/
@Test
@DependsOnMethod("testSimple")
public void testNested() {
final InternationalString title = new SimpleInternationalString("Some title");
final InternationalString person = new SimpleInternationalString("Illustre inconnu");
final DefaultIndividual party = new DefaultIndividual(person, null, null);
final DefaultResponsibleParty resp = new DefaultResponsibleParty(Role.AUTHOR);
final DefaultCitation instance = new DefaultCitation(title);
resp.getParties().add(party);
instance.getCitedResponsibleParties().add(resp);
/*
* Individual hash code is the sum of all its properties, none of them being a collection.
*/
int expected = DefaultIndividual.class.hashCode() + person.hashCode();
assertEquals("Individual", Integer.valueOf(expected), hash(party));
/*
* The +31 below come from java.util.List contract, since above Individual is a list member.
*/
expected += ResponsibleParty.class.hashCode() + Role.AUTHOR.hashCode() + 31;
assertEquals("Responsibility", Integer.valueOf(expected), hash(resp));
/*
* The +31 below come from java.util.List contract, since above Responsibility is a list member.
*/
expected += Citation.class.hashCode() + title.hashCode() + 31;
assertEquals("Citation", Integer.valueOf(expected), hash(instance));
}
/**
* Tests hash code computation of an object graph containing a cycle.
*/
@Test
@DependsOnMethod("testNested")
public void testCycle() {
/*
* We will create a Platform and an Instrument, both of them with no other property than an identifier.
* The assertions verifying Identifier hash codes are not the main purpose of this test, but we perform
* those verifications for making sure that the assertion done at the end of this method has good premises.
*/
final DefaultIdentifier platformID = new DefaultIdentifier("P1");
final DefaultIdentifier instrumentID = new DefaultIdentifier("I1");
int platformHash = Identifier.class.hashCode() + platformID.getCode().hashCode();
int instrumentHash = Identifier.class.hashCode() + instrumentID.getCode().hashCode();
assertEquals("platformID", Integer.valueOf(platformHash), hash(platformID));
assertEquals("instrumentID", Integer.valueOf(instrumentHash), hash(instrumentID));
/*
* Verify Platform and Instrument hash codes before we link them together.
*/
final DefaultPlatform platform = new DefaultPlatform();
final DefaultInstrument instrument = new DefaultInstrument();
platform .setIdentifier(platformID);
instrument.setIdentifier(instrumentID);
platformHash += Platform.class.hashCode();
instrumentHash += Instrument.class.hashCode();
assertEquals("Platform", Integer.valueOf(platformHash), hash(platform));
assertEquals("Instrument", Integer.valueOf(instrumentHash), hash(instrument));
/*
* Add the instrument to the platform. The +31 below come from java.util.List contract,
* since the Instrument is contained in a list.
*/
platform.getInstruments().add(instrument);
platformHash += instrumentHash + 31;
assertEquals("Platform", Integer.valueOf(platformHash), hash(platform));
/*
* Add a reference from the instrument back to the platform. This is where the graph become cyclic.
* The hash code computation is expected to behave as if the platform was not specified.
*/
instrument.setMountedOn(platform);
assertEquals("Platform", Integer.valueOf(platformHash), hash(platform));
}
}