| /* |
| * 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.iso.citation; |
| |
| import java.util.Iterator; |
| import java.util.Collection; |
| import java.util.Collections; |
| import javax.xml.bind.annotation.XmlType; |
| import javax.xml.bind.annotation.XmlElement; |
| import javax.xml.bind.annotation.XmlRootElement; |
| import org.opengis.metadata.citation.Contact; |
| import org.opengis.metadata.citation.ResponsibleParty; |
| import org.opengis.metadata.citation.Role; |
| import org.opengis.util.InternationalString; |
| import org.apache.sis.util.iso.Types; |
| import org.apache.sis.internal.xml.LegacyNamespaces; |
| import org.apache.sis.internal.metadata.Dependencies; |
| import org.apache.sis.internal.metadata.legacy.LegacyPropertyAdapter; |
| |
| import static org.apache.sis.internal.metadata.MetadataUtilities.valueIfDefined; |
| |
| |
| /** |
| * Identification of, and means of communication with, person(s) and |
| * organizations associated with the dataset. |
| * The following properties are mandatory or conditional (i.e. mandatory under some circumstances) |
| * in a well-formed metadata according ISO 19115: |
| * |
| * <div class="preformat">{@code CI_ResponsibleParty} |
| * {@code ├─role……………………………} Function performed by the responsible party. |
| * {@code └─party…………………………} Information about the parties. |
| * {@code └─name…………………} Name of the party.</div> |
| * |
| * <div class="warning"><b>Upcoming API change — deprecation</b><br> |
| * As of ISO 19115:2014, the {@code ResponsibleParty} type has been replaced by {@code Responsibility} |
| * to allow more flexible associations of individuals, organisations, and roles. |
| * This {@code ResponsibleParty} interface may be deprecated in GeoAPI 4.0. |
| * </div> |
| * |
| * @author Martin Desruisseaux (IRD, Geomatys) |
| * @author Touraïvane (IRD) |
| * @author Cédric Briançon (Geomatys) |
| * @version 1.0 |
| * @since 0.3 |
| * @module |
| */ |
| @XmlType(name = "CI_ResponsibleParty_Type", namespace = LegacyNamespaces.GMD, propOrder = { |
| "individualName", |
| "organisationName", |
| "positionName", |
| "contactInfo", |
| "role" |
| }) |
| @XmlRootElement(name = "CI_ResponsibleParty", namespace = LegacyNamespaces.GMD) |
| public class DefaultResponsibleParty extends DefaultResponsibility implements ResponsibleParty { |
| /** |
| * Serial number for inter-operability with different versions. |
| */ |
| private static final long serialVersionUID = -1022635486627088812L; |
| |
| /** |
| * Constructs an initially empty responsible party. |
| */ |
| public DefaultResponsibleParty() { |
| } |
| |
| /** |
| * Constructs a responsibility party with the given role. |
| * |
| * @param role the function performed by the responsible party, or {@code null}. |
| */ |
| public DefaultResponsibleParty(final Role role) { |
| super(role, null, null); |
| } |
| |
| /** |
| * Constructs a new instance initialized with the values from the specified metadata object. |
| * This is a <cite>shallow</cite> copy constructor, since the other metadata contained in the |
| * given object are not recursively copied. |
| * |
| * @param object the metadata to copy values from, or {@code null} if none. |
| */ |
| public DefaultResponsibleParty(final DefaultResponsibility object) { |
| super(object); |
| } |
| |
| /** |
| * Constructs a new instance initialized with the values from the specified metadata object. |
| * This is a <cite>shallow</cite> copy constructor, since the other metadata contained in the |
| * given object are not recursively copied. |
| * |
| * @param object The metadata to copy values from, or {@code null} if none. |
| * |
| * @see #castOrCopy(ResponsibleParty) |
| */ |
| public DefaultResponsibleParty(final ResponsibleParty object) { |
| super(object); |
| if (object != null && !(object instanceof DefaultResponsibility)) { |
| setIndividualName(object.getIndividualName()); |
| setOrganisationName(object.getOrganisationName()); |
| } |
| } |
| |
| /** |
| * Returns a SIS metadata implementation with the values of the given arbitrary implementation. |
| * This method performs the first applicable action in the following choices: |
| * |
| * <ul> |
| * <li>If the given object is {@code null}, then this method returns {@code null}.</li> |
| * <li>Otherwise if the given object is already an instance of |
| * {@code DefaultResponsibleParty}, then it is returned unchanged.</li> |
| * <li>Otherwise a new {@code DefaultResponsibleParty} instance is created using the |
| * {@linkplain #DefaultResponsibleParty(ResponsibleParty) copy constructor} |
| * and returned. Note that this is a <cite>shallow</cite> copy operation, since the other |
| * metadata contained in the given object are not recursively copied.</li> |
| * </ul> |
| * |
| * @param object the object to get as a SIS implementation, or {@code null} if none. |
| * @return a SIS implementation containing the values of the given object (may be the |
| * given object itself), or {@code null} if the argument was null. |
| */ |
| public static DefaultResponsibleParty castOrCopy(final ResponsibleParty object) { |
| if (object == null || object instanceof DefaultResponsibleParty) { |
| return (DefaultResponsibleParty) object; |
| } |
| return new DefaultResponsibleParty(object); |
| } |
| |
| /** |
| * Returns the name or the position of the first individual. If no individual is found in the list of parties, |
| * then this method will search in the list of organization members. The later structure is used by our netCDF |
| * reader. |
| * |
| * @param position {@code true} for returning the position name instead than individual name. |
| * @return the name or position of the first individual, or {@code null}. |
| * |
| * @see #getIndividualName() |
| * @see #getPositionName() |
| */ |
| private InternationalString getIndividual(final boolean position) { |
| final Collection<AbstractParty> parties = getParties(); |
| InternationalString name = getName(parties, DefaultIndividual.class, position); |
| if (name == null && parties != null) { |
| for (final AbstractParty party : parties) { |
| if (party instanceof DefaultOrganisation) { |
| name = getName(((DefaultOrganisation) party).getIndividual(), DefaultIndividual.class, position); |
| if (name != null) { |
| break; |
| } |
| } |
| } |
| } |
| return name; |
| } |
| |
| /** |
| * Returns the name of the first party of the given type, or {@code null} if none. |
| * |
| * @param position {@code true} for returning the position name instead than individual name. |
| * @return the name or position of the first individual, or {@code null}. |
| * |
| * @see #getOrganisationName() |
| * @see #getIndividualName() |
| * @see #getPositionName() |
| */ |
| private static InternationalString getName(final Collection<? extends AbstractParty> parties, |
| final Class<? extends AbstractParty> type, final boolean position) |
| { |
| InternationalString name = null; |
| if (parties != null) { // May be null on marshalling. |
| for (final AbstractParty party : parties) { |
| if (type.isInstance(party)) { |
| if (name != null) { |
| LegacyPropertyAdapter.warnIgnoredExtraneous(type, DefaultResponsibleParty.class, |
| position ? "getPositionName" : (type == DefaultIndividual.class) |
| ? "getIndividualName" : "getOrganisationName"); |
| break; |
| } |
| name = position ? ((DefaultIndividual) party).getPositionName() : party.getName(); |
| } |
| } |
| } |
| return name; |
| } |
| |
| /** |
| * Sets the name of the first party of the given type. |
| * |
| * @return {@code true} if the name has been set, or {@code false} otherwise. |
| */ |
| private boolean setName(final Class<? extends AbstractParty> type, final boolean position, final InternationalString name) { |
| checkWritePermission(valueIfDefined(super.getParties())); |
| final Iterator<AbstractParty> it = getParties().iterator(); |
| while (it.hasNext()) { |
| final AbstractParty party = it.next(); |
| if (type.isInstance(party)) { |
| if (position) { |
| ((DefaultIndividual) party).setPositionName(name); |
| } else { |
| party.setName(name); |
| } |
| if (party.isEmpty()) { |
| it.remove(); |
| } |
| return true; |
| } |
| } |
| return name == null; // If no party and name is null, there is nothing to set. |
| } |
| |
| /** |
| * Returns the name of the responsible person- surname, given name, title separated by a delimiter. |
| * Only one of {@code individualName}, {@link #getOrganisationName() organisationName} |
| * and {@link #getPositionName() positionName} shall be provided. |
| * |
| * <p>This implementation returns the name of the first {@code Individual} found in the collection of |
| * {@linkplain #getParties() parties}. If no individual is found in the parties, then this method fallbacks |
| * on the first organisation member.</p> |
| * |
| * @return name, surname, given name and title of the responsible person, or {@code null}. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@code getName()} in {@link DefaultIndividual}. |
| */ |
| @Override |
| @Deprecated |
| @Dependencies("getParties") |
| @XmlElement(name = "individualName") |
| public String getIndividualName() { |
| final InternationalString name = getIndividual(false); |
| return (name != null) ? name.toString() : null; |
| } |
| |
| /** |
| * Sets the name of the responsible person- surname, given name, title separated by a delimiter. |
| * Only one of {@code individualName}, {@link #getOrganisationName() organisationName} |
| * and {@link #getPositionName() positionName} shall be provided. |
| * |
| * <p>This implementation sets the name of the first {@code Individual} found in the collection of |
| * {@linkplain #getParties() parties}, or create a new individual if no existing instance was found.</p> |
| * |
| * @param newValue the new individual name, or {@code null} if none. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@code setName(InternationalString)} in {@link DefaultIndividual}. |
| */ |
| @Deprecated |
| public void setIndividualName(final String newValue) { |
| if (!setName(DefaultIndividual.class, false, Types.toInternationalString(newValue))) { |
| getParties().add(new DefaultIndividual(newValue, null, null)); |
| } |
| } |
| |
| /** |
| * Returns the name of the responsible organization. Only one of |
| * {@link #getIndividualName() individualName}, {@code organisationName} |
| * and {@link #getPositionName() positionName} shall be provided. |
| * |
| * <p>This implementation returns the name of the first {@code Organisation} |
| * found in the collection of {@linkplain #getParties() parties}.</p> |
| * |
| * @return name of the responsible organization, or {@code null}. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@code getName()} in {@link DefaultOrganisation}. |
| */ |
| @Override |
| @Deprecated |
| @XmlElement(name = "organisationName") |
| @Dependencies("getParties") |
| public InternationalString getOrganisationName() { |
| return getName(getParties(), DefaultOrganisation.class, false); |
| } |
| |
| /** |
| * Sets the name of the responsible organization. Only one of |
| * {@link #getIndividualName() individualName}, {@code organisationName} |
| * and {@link #getPositionName() positionName} shall be provided. |
| * |
| * <p>This implementation sets the name of the first {@code Organisation} found in the collection of |
| * {@linkplain #getParties() parties}, or create a new organization if no existing instance was found.</p> |
| * |
| * @param newValue the new organization name, or {@code null} if none. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@code setName(InternationalString)} in {@link DefaultOrganisation}. |
| */ |
| @Deprecated |
| public void setOrganisationName(final InternationalString newValue) { |
| if (!setName(DefaultOrganisation.class, false, Types.toInternationalString(newValue))) { |
| getParties().add(new DefaultOrganisation(newValue, null, null, null)); |
| } |
| } |
| |
| /** |
| * Returns the role or position of the responsible person Only one of |
| * {@link #getIndividualName() individualName}, {@link #getOrganisationName() organisationName} |
| * and {@code positionName} shall be provided. |
| * |
| * <p>This implementation returns the position of the first {@code Individual} found in the collection of |
| * {@linkplain #getParties() parties}. If no individual is found in the parties, then this method fallbacks |
| * on the first organisation member.</p> |
| * |
| * @return role or position of the responsible person, or {@code null} |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@link DefaultIndividual#getPositionName()}. |
| */ |
| @Override |
| @Deprecated |
| @XmlElement(name = "positionName") |
| @Dependencies("getParties") |
| public InternationalString getPositionName() { |
| return getIndividual(true); |
| } |
| |
| /** |
| * set the role or position of the responsible person Only one of |
| * {@link #getIndividualName() individualName}, {@link #getOrganisationName() organisationName} |
| * and {@code positionName} shall be provided. |
| * |
| * <p>This implementation sets the position name of the first {@code Individual} found in the collection of |
| * {@linkplain #getParties() parties}, or create a new individual if no existing instance was found.</p> |
| * |
| * @param newValue the new position name, or {@code null} if none. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@link DefaultIndividual#setPositionName(InternationalString)}. |
| */ |
| @Deprecated |
| public void setPositionName(final InternationalString newValue) { |
| if (!setName(DefaultIndividual.class, true, newValue)) { |
| getParties().add(new DefaultIndividual(null, newValue, null)); |
| } |
| } |
| |
| /** |
| * Returns the address of the responsible party. |
| * |
| * <p>This implementation returns the first non-null contact found in the collection of |
| * {@linkplain #getParties() parties}.</p> |
| * |
| * @return address of the responsible party, or {@code null}. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@link AbstractParty#getContactInfo()}. |
| */ |
| @Override |
| @Deprecated |
| @XmlElement(name = "contactInfo") |
| @Dependencies("getParties") |
| public Contact getContactInfo() { |
| final Collection<AbstractParty> parties = getParties(); |
| if (parties != null) { // May be null on marshalling. |
| for (final AbstractParty party : parties) { |
| final Collection<? extends Contact> contacts = party.getContactInfo(); |
| if (contacts != null) { // May be null on marshalling. |
| for (final Contact contact : contacts) { |
| if (contact != null) { // Paranoiac check. |
| return contact; |
| } |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Sets the address of the responsible party. |
| * |
| * <p>This implementation sets the contact info in the first party found in the collection of |
| * {@linkplain #getParties() parties}.</p> |
| * |
| * @param newValue the new contact info, or {@code null} if none. |
| * |
| * @deprecated As of ISO 19115:2014, replaced by {@link AbstractParty#setContactInfo(Collection)}. |
| */ |
| @Deprecated |
| public void setContactInfo(final Contact newValue) { |
| checkWritePermission(valueIfDefined(super.getParties())); |
| final Iterator<AbstractParty> it = getParties().iterator(); |
| while (it.hasNext()) { |
| final AbstractParty party = it.next(); |
| party.setContactInfo(newValue != null ? Collections.singleton(newValue) : null); |
| if (party.isEmpty()) { |
| it.remove(); |
| } |
| return; |
| } |
| /* |
| * If no existing AbstractParty were found, add a new one. However there is no way to know if |
| * it should be an individual or an organization. Arbitrarily choose an individual for now. |
| */ |
| if (newValue != null) { |
| getParties().add(new DefaultIndividual(null, null, newValue)); |
| } |
| } |
| |
| /** |
| * Returns the function performed by the responsible party. |
| * |
| * @return function performed by the responsible party. |
| */ |
| @Override |
| @XmlElement(name = "role", required = true) |
| public Role getRole() { |
| return super.getRole(); |
| } |
| |
| /** |
| * Sets the function performed by the responsible party. |
| * |
| * @param newValue the new role. |
| */ |
| @Override |
| public void setRole(final Role newValue) { |
| super.setRole(newValue); |
| } |
| } |