| /* |
| * 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.simple; |
| |
| import java.util.Date; |
| import java.util.Collection; |
| import java.io.ObjectStreamException; |
| import org.opengis.metadata.Identifier; |
| import org.opengis.metadata.citation.Citation; |
| import org.opengis.metadata.citation.CitationDate; |
| import org.opengis.metadata.citation.OnlineResource; |
| import org.opengis.metadata.citation.PresentationForm; |
| import org.opengis.metadata.citation.ResponsibleParty; |
| import org.opengis.metadata.citation.Series; |
| import org.opengis.metadata.identification.BrowseGraphic; |
| import org.opengis.util.InternationalString; |
| import org.apache.sis.xml.IdentifierSpace; |
| import org.apache.sis.metadata.sql.MetadataSource; |
| import org.apache.sis.metadata.sql.MetadataStoreException; |
| import org.apache.sis.metadata.iso.citation.Citations; |
| import org.apache.sis.internal.system.Loggers; |
| import org.apache.sis.internal.util.Strings; |
| import org.apache.sis.util.logging.Logging; |
| |
| |
| /** |
| * Base class for the {@code public static final Citation} constants defined in some SIS classes. |
| * This base class contains only an abbreviation (e.g. {@code "OGC"} or {@code "EPSG"}) which can |
| * be used as the primary key where to search for more information in a database. If no database |
| * is available, then that simple primary key will be used as the citation title. |
| * |
| * @author Martin Desruisseaux (Geomatys) |
| * @version 1.0 |
| * |
| * @see IdentifierSpace |
| * @see Citations |
| * |
| * @since 0.6 |
| * @module |
| */ |
| public class CitationConstant extends SimpleCitation { |
| /** |
| * For cross-version compatibility. |
| */ |
| private static final long serialVersionUID = -8429121584437634107L; |
| |
| /** |
| * Class of {@code public static final Citation} constants which are also used as namespace for identifiers. |
| * The most typical example is the "EPSG" authority which manage the codes identifying Coordinate Reference |
| * System (CRS) objects in the EPSG namespace. |
| * |
| * @param <T> the type of object used as identifier values. |
| */ |
| public static class Authority<T> extends CitationConstant implements IdentifierSpace<T> { |
| /** |
| * For cross-version compatibility. |
| */ |
| private static final long serialVersionUID = 2067932813561130294L; |
| |
| /** |
| * Creates a new citation for an authority managing codes in the given namespace. |
| * This constructor assumes that the namespace is the same as the abbreviation given as citation title. |
| * |
| * @param namespace the namespace of codes managed by this authority (e.g. "EPSG"). |
| */ |
| public Authority(final String namespace) { |
| super(namespace); |
| } |
| |
| /** |
| * Creates a new citation for an authority managing codes in the given namespace. |
| * |
| * @param name a human-understandable primary key for fetching more information. |
| * @param namespace the namespace of codes managed by this authority (e.g. "EPSG"). |
| */ |
| public Authority(final String name, final String namespace) { |
| super(name, namespace); |
| } |
| |
| /** |
| * Returns the name space given at construction time. Can be one of the following: |
| * <ul> |
| * <li>Abbreviation of the authority managing the codes (e.g. {@code "EPSG"} or {@code "ISBN"}).</li> |
| * <li>XML attribute name with its prefix (e.g. {@code "gml:id"}, {@code "gco:uuid"} or {@code "xlink:href"}).</li> |
| * </ul> |
| */ |
| @Override |
| public final String getName() { |
| return namespace; |
| } |
| |
| /** |
| * Returns a string representation of this identifier space. |
| */ |
| @Override |
| public final String toString() { |
| return Strings.bracket(IdentifierSpace.class, title); |
| } |
| } |
| |
| /** |
| * The name by which this citation is known to {@link Citations#fromName(String)}. |
| * Often the same than the abbreviation that {@link CitationConstant} uses as the title. |
| * If this {@code CitationConstant} is a {@link Authority} subtype, then this is also |
| * the authority namespace. |
| */ |
| public final String namespace; |
| |
| /** |
| * The citation which contain the "real" data, or {@code null} if not yet created. |
| * This is usually an instance created by {@link MetadataSource}. Those instances |
| * manage their own caching, so accesses to the database should not occur often. |
| */ |
| private transient volatile Citation delegate; |
| |
| /** |
| * Creates a new proxy for the given primary key. |
| * The key should be readable enough for being usable as a fallback if the database is not available. |
| * |
| * @param name a human-understandable primary key for fetching more information. |
| */ |
| public CitationConstant(final String name) { |
| super(name); |
| this.namespace = name; |
| } |
| |
| /** |
| * Creates a new proxy for the given primary key but a different programmatic name. |
| * The key should be readable enough for being usable as a fallback if the database is not available. |
| * |
| * @param name a human-understandable primary key for fetching more information. |
| * @param namespace the name by which this citation is known to {@link Citations#fromName(String)}. |
| */ |
| public CitationConstant(final String name, final String namespace) { |
| super(name); |
| this.namespace = namespace; |
| } |
| |
| /** |
| * Notify this instance that the database content may have changed, or that the classpath has changed. |
| */ |
| public final void refresh() { |
| delegate = null; |
| } |
| |
| /** |
| * Returns the citation instance which contain the actual data. That instance is provided by the |
| * {@code sis-metadata} module, which is optional. If that module is not on the classpath, then |
| * this {@code delegate()} method will use the few information provided by the current instance. |
| * |
| * <p>Note that it should be very rare to not have {@code sis-metadata} on the classpath, |
| * since that module is required by {@code sis-referencing} which is itself required by |
| * almost all other SIS modules.</p> |
| */ |
| @SuppressWarnings("DoubleCheckedLocking") |
| private Citation delegate() { |
| Citation c = delegate; |
| if (c == null) { |
| synchronized (this) { |
| c = delegate; |
| if (c == null) { |
| try { |
| c = MetadataSource.getProvided().lookup(Citation.class, title); |
| } catch (MetadataStoreException e) { |
| /* |
| * If no database was available, MetadataSource.getProvided() was supposed to fallback on |
| * the MetadataFallback class. So if we get this exception, a more serious error occurred. |
| * It is still not fatal however, since most of Citation content is informative. |
| */ |
| Logging.unexpectedException(Logging.getLogger(Loggers.SQL), CitationConstant.class, "delegate", e); |
| c = new SimpleCitation(title); |
| } |
| delegate = c; |
| } |
| } |
| } |
| return c; |
| } |
| |
| /** |
| * Redirects the call to the delegate citation (the instance which actually contain the data). |
| * |
| * @return the value returned by the delegate. |
| */ |
| @Override public InternationalString getTitle() {return delegate().getTitle();} |
| @Override public Collection<? extends InternationalString> getAlternateTitles() {return delegate().getAlternateTitles();} |
| @Override public Collection<? extends CitationDate> getDates() {return delegate().getDates();} |
| @Override public InternationalString getEdition() {return delegate().getEdition();} |
| @Override public Date getEditionDate() {return delegate().getEditionDate();} |
| @Override public Collection<? extends Identifier> getIdentifiers() {return delegate().getIdentifiers();} |
| @Override public Collection<? extends ResponsibleParty> getCitedResponsibleParties() {return delegate().getCitedResponsibleParties();} |
| @Override public Collection<PresentationForm> getPresentationForms() {return delegate().getPresentationForms();} |
| @Override public Series getSeries() {return delegate().getSeries();} |
| @Override public InternationalString getOtherCitationDetails() {return delegate().getOtherCitationDetails();} |
| @Override public Collection<? extends OnlineResource> getOnlineResources() {return delegate().getOnlineResources();} |
| @Override public Collection<? extends BrowseGraphic> getGraphics() {return delegate().getGraphics();} |
| @Override public String getISBN() {return delegate().getISBN();} |
| @Override public String getISSN() {return delegate().getISSN();} |
| |
| /** |
| * Invoked at deserialization time in order to replace the deserialized instance by the existing |
| * instance defined in the {@link org.apache.sis.metadata.iso.citation.Citations} class. |
| * |
| * @return the instance to use, as an unique instance if possible. |
| * @throws ObjectStreamException never thrown. |
| */ |
| protected Object readResolve() throws ObjectStreamException { |
| final Citation c = Citations.fromName(title); |
| return (c instanceof CitationConstant) ? c : this; |
| /* |
| * Returns 'this' should happen only if the Citation has been serialized |
| * on a more recent version of Apache SIS than the current version. |
| */ |
| } |
| } |