blob: a2f335773a306e2be203d2d8454330de576ec8d1 [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.internal.storage.gpx;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Locale;
import java.util.Objects;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.opengis.metadata.citation.Address;
import org.opengis.metadata.citation.Contact;
import org.opengis.metadata.citation.OnlineResource;
import org.opengis.metadata.citation.Role;
import org.opengis.metadata.citation.Telephone;
import org.opengis.util.InternationalString;
import org.apache.sis.util.iso.SimpleInternationalString;
import org.apache.sis.util.iso.Types;
// Branch-dependent imports
import org.opengis.metadata.citation.Party;
import org.opengis.metadata.citation.Responsibility;
import org.opengis.metadata.citation.ResponsibleParty;
/**
* Information about a person or organization.
* This element provides 3 optional properties:
*
* <ul>
* <li>The {@linkplain #name}.</li>
* <li>The person {@linkplain #email}.</li>
* <li>An URI to other information about the person or organization.</li>
* </ul>
*
* Those properties can be read or modified directly. All methods defined in this class are bridges to
* the ISO 19115 metadata model and can be ignored if the user only wants to manipulate the GPX model.
*
* <p>Note that {@link Party} is an abstract type in ISO 19115 model. We are supposed to implement a subtype
* ({@link org.opengis.metadata.citation.Individual} or {@link org.opengis.metadata.citation.Organisation}).
* However the GPX metadata does not specifies whether the "person" is actually an individual or an organization.
* In this situation of doubt, we do not select a subtype for avoiding to provide a wrong information.</p>
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @version 0.8
* @since 0.8
* @module
*/
public final class Person implements ResponsibleParty, Party, Contact, Address {
/**
* Name of person or organization.
*
* @see #getName()
*/
@XmlElement(name = Tags.NAME)
public String name;
/**
* {@code true} if this name is the creator, {@code false} if it is the author.
*/
boolean isCreator;
/**
* Email address.
*
* @see #getElectronicMailAddresses()
*/
@XmlElement(name = Tags.EMAIL)
@XmlJavaTypeAdapter(Email.class)
public String email;
/**
* Link to Web site or other external information about person.
*
* @see #getOnlineResources()
*/
@XmlElement(name = Tags.LINK)
public Link link;
/**
* Creates an initially empty instance.
*/
public Person() {
}
/**
* Creates an instance for the given creator.
*/
Person(final String creator) {
name = creator;
isCreator = true;
}
/**
* Returns the given ISO 19115 metadata as a {@code Person} instance.
* This method copies the data only if needed.
*
* @param r the ISO 19115 metadata, or {@code null}.
* @param locale the locale to use for localized strings.
* @return the GPX metadata, or {@code null}.
*/
public static Person castOrCopy(final Responsibility r, final Locale locale) {
if (r == null || r instanceof Person) {
return (Person) r;
}
final Role role = r.getRole();
final boolean isCreator = Role.ORIGINATOR.equals(role);
if (isCreator || Role.AUTHOR.equals(role)) {
for (final Party p : r.getParties()) {
final String name = Types.toString(p.getName(), locale);
if (name != null) {
final Person pr = new Person();
pr.name = name;
pr.isCreator = isCreator;
return pr;
}
}
}
return null;
}
/**
* ISO 19115 metadata property fixed to {@link Role#ORIGINATOR} or {@link Role#AUTHOR}.
*
* @return function performed by the responsible party.
*/
@Override
public Role getRole() {
return isCreator ? Role.ORIGINATOR : Role.AUTHOR;
}
/**
* ISO 19115 metadata property determined by the {@link #name}, {@link #email} and {@link #link} fields.
* Invoking this method is one of the steps in the path from the {@code Responsibility} root to the
* {@link #getName()}, {@link #getElectronicMailAddresses()} and {@link #getOnlineResources()} methods.
*
* @return information about the parties.
*
* @see #getName()
* @see #getContactInfo()
*/
@Override
public Collection<? extends Party> getParties() {
return thisOrEmpty(name != null || email != null || link != null);
}
/* ---------------------------------------------------------------------------------
* Implementation of the Party object returned by Responsibility.getParties().
* Contains information about 'name', 'email' and 'link'.
* --------------------------------------------------------------------------------- */
/**
* ISO 19115 metadata property determined by the {@link #name} field.
*
* @return name of the party, or {@code null} if none.
*/
@Override
public InternationalString getName() {
return (name != null) ? new SimpleInternationalString(name) : null;
}
/**
* ISO 19115 metadata property not specified by GPX. Actually could be the {@link #name},
* but we have no way to know if the author is an individual or an organization.
*
* @return name of the organization, or {@code null} if none.
*/
@Override
public InternationalString getOrganisationName() {
return null;
}
/**
* ISO 19115 metadata property not specified by GPX.
*
* @return position of the individual in the organization, or {@code null} if none.
*/
@Override
public InternationalString getPositionName() {
return null;
}
/**
* ISO 19115 metadata property determined by the {@link #name} field.
*
* @return name of the party, or {@code null} if none.
*/
@Override
public String getIndividualName() {
return name;
}
/**
* ISO 19115 metadata property determined by the {@link #email} and {@link #link} fields.
* Invoking this method is one of the steps in the path from the {@code Responsibility} root
* to the {@link #getElectronicMailAddresses()} and {@link #getOnlineResources()} methods.
*
* @return contact information for the party.
*
* @see #getAddresses()
* @see #getOnlineResources()
*/
@Override
public Proxy getContactInfo() { // Both Contact singleton and Collection<Contact>.
return new Proxy();
}
private final class Proxy extends AbstractSet<Contact> implements Contact {
@Override public int size() {
return (email != null || link != null) ? 1 : 0;
}
@Override public Iterator<Contact> iterator() {
return Collections.<Contact>singleton(Person.this).iterator();
}
@Override public Collection<? extends Telephone> getPhones() {return Person.this.getPhones();}
@Override public Telephone getPhone() {return Person.this.getPhone();}
@Override public Collection<? extends Address> getAddresses() {return Person.this.getAddresses();}
@Override public Address getAddress() {return Person.this.getAddress();}
@Override public Collection<OnlineResource> getOnlineResources() {return Person.this.getOnlineResources();}
@Override public OnlineResource getOnlineResource() {return Person.this.getOnlineResource();}
@Override public InternationalString getHoursOfService() {return Person.this.getHoursOfService();}
@Override public InternationalString getContactInstructions() {return Person.this.getContactInstructions();}
@Override public InternationalString getContactType() {return Person.this.getContactType();}
}
/* ---------------------------------------------------------------------------------
* Implementation of the Contact object returned by Party.getContactInfo().
* Contains information about 'email' and 'link' only (not 'name').
* --------------------------------------------------------------------------------- */
/**
* ISO 19115 metadata property determined by the {@link #email} field.
* Invoking this method is one of the steps in the path from the {@code Responsibility} root
* to the {@link #getElectronicMailAddresses()} method.
*
* @return physical and email addresses at which the organization or individual may be contacted.
*
* @see #getElectronicMailAddresses()
*/
@Override
public Collection<? extends Address> getAddresses() {
return thisOrEmpty(email != null);
}
/**
* ISO 19115 metadata property determined by the {@link #link} field.
*
* @return on-line information that can be used to contact the individual or organization.
*/
@Override
public Collection<OnlineResource> getOnlineResources() {
return (link != null) ? Collections.singleton(link) : Collections.emptySet();
}
/* ---------------------------------------------------------------------------------
* Implementation of the Address object returned by Contact.getAddresses().
* Contains information about 'email' only (not 'name' or 'link').
* --------------------------------------------------------------------------------- */
/**
* ISO 19115 metadata property determined by the {@link #email} field.
*
* @return address of the electronic mailbox of the responsible organization or individual.
*/
@Override
public Collection<String> getElectronicMailAddresses() {
return (email != null) ? Collections.singleton(email) : Collections.emptySet();
}
/**
* Returns this object as a singleton if the given condition is {@code true},
* or an empty set if the given condition is {@code false}.
*/
private Collection<Person> thisOrEmpty(final boolean condition) {
return condition ? Collections.singleton(this) : Collections.emptySet();
}
/**
* Compares this {@code Person} with the given object for equality.
*
* @param obj the object to compare with this {@code Person}.
* @return {@code true} if both objects are equal.
*/
@Override
public boolean equals(final Object obj) {
if (obj instanceof Person) {
final Person that = (Person) obj;
return Objects.equals(this.name, that.name) &&
Objects.equals(this.email, that.email) &&
Objects.equals(this.link, that.link);
}
return false;
}
/**
* Returns a hash code value for this {@code Person}.
*
* @return a hash code value.
*/
@Override
public int hashCode() {
return Objects.hash(name, email, link);
}
/**
* Returns a string representation of this person statement.
* The statement is formatted in a way similar to the email address in client software applications.
* Example:
*
* <blockquote>
* John Smith {@literal <john.smith@somewhere.com>}
* http://john.smith.com
* </blockquote>
*
* @return a string representation of this person.
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
if (name != null) {
sb.append(name);
}
if (email != null) {
if (sb.length() != 0) sb.append(' ');
sb.append('<').append(email).append('>');
}
if (link != null) {
if (sb.length() != 0) {
sb.append(System.lineSeparator());
}
sb.append(link);
}
return sb.toString();
}
}