Search in sources :

Example 1 with Dependencies

use of org.apache.sis.internal.metadata.Dependencies in project sis by apache.

the class PropertyConsistencyCheck method testDependenciesAnnotation.

/**
 * Verifies the {@link Dependencies} annotations. This method verifies that the annotation is applied on
 * deprecated getter methods, that the referenced properties exist and the getter methods of referenced
 * properties are not deprecated.
 *
 * @throws NoSuchMethodException if {@link PropertyAccessor} references a non-existent method (would be a bug).
 *
 * @since 0.8
 */
@Test
public void testDependenciesAnnotation() throws NoSuchMethodException {
    for (final Class<?> type : types) {
        final Class<?> impl = standard.getImplementation(type);
        if (impl != null) {
            Map<String, String> names = null;
            for (final Method method : impl.getDeclaredMethods()) {
                final Dependencies dep = method.getAnnotation(Dependencies.class);
                if (dep != null) {
                    final String name = method.getName();
                    if (names == null) {
                        names = standard.asNameMap(type, KeyNamePolicy.JAVABEANS_PROPERTY, KeyNamePolicy.METHOD_NAME);
                    }
                    /*
                         * Currently, @Dependencies is applied only on deprecated getter methods.
                         * However this policy may change in future Apache SIS versions.
                         */
                    assertTrue(name, name.startsWith("get"));
                    assertTrue(name, method.isAnnotationPresent(Deprecated.class));
                    /*
                         * All dependencies shall be non-deprecated methods. Combined with above
                         * restriction about @Dependencies applied only on deprected methods, this
                         * ensure that there is no cycle.
                         */
                    for (final String ref : dep.value()) {
                        // Verify that the dependency is a property name.
                        assertEquals(name, names.get(ref), ref);
                        // Verify that the referenced method is non-deprecated.
                        assertFalse(name, impl.getMethod(names.get(ref)).isAnnotationPresent(Deprecated.class));
                    }
                }
            }
        }
    }
}
Also used : Method(java.lang.reflect.Method) Dependencies(org.apache.sis.internal.metadata.Dependencies) Test(org.junit.Test)

Example 2 with Dependencies

use of org.apache.sis.internal.metadata.Dependencies in project sis by apache.

the class DefaultMetadata method getDataSetUri.

/**
 * Provides the URI of the dataset to which the metadata applies.
 *
 * @return Uniform Resource Identifier of the dataset, or {@code null}.
 *
 * @deprecated As of ISO 19115:2014, replaced by {@link #getIdentificationInfo()} followed by
 *    {@link DefaultDataIdentification#getCitation()} followed by {@link DefaultCitation#getOnlineResources()}.
 */
@Override
@Deprecated
@Dependencies("getIdentificationInfo")
@XmlElement(name = "dataSetURI", namespace = LegacyNamespaces.GMD)
public String getDataSetUri() {
    String linkage = null;
    final Collection<Identification> info;
    if (FilterByVersion.LEGACY_METADATA.accept() && (info = getIdentificationInfo()) != null) {
        for (final Identification identification : info) {
            final Citation citation = identification.getCitation();
            if (citation instanceof DefaultCitation) {
                final Collection<? extends OnlineResource> onlineResources = ((DefaultCitation) citation).getOnlineResources();
                if (onlineResources != null) {
                    for (final OnlineResource link : onlineResources) {
                        final URI uri = link.getLinkage();
                        if (uri != null) {
                            if (linkage == null) {
                                linkage = uri.toString();
                            } else {
                                LegacyPropertyAdapter.warnIgnoredExtraneous(OnlineResource.class, DefaultMetadata.class, "getDataSetUri");
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    return linkage;
}
Also used : OnlineResource(org.opengis.metadata.citation.OnlineResource) DefaultOnlineResource(org.apache.sis.metadata.iso.citation.DefaultOnlineResource) DefaultCitation(org.apache.sis.metadata.iso.citation.DefaultCitation) DefaultDataIdentification(org.apache.sis.metadata.iso.identification.DefaultDataIdentification) Identification(org.opengis.metadata.identification.Identification) AbstractIdentification(org.apache.sis.metadata.iso.identification.AbstractIdentification) InternationalString(org.opengis.util.InternationalString) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) Citation(org.opengis.metadata.citation.Citation) DefaultCitation(org.apache.sis.metadata.iso.citation.DefaultCitation) CI_Citation(org.apache.sis.internal.jaxb.metadata.CI_Citation) URI(java.net.URI) XmlElement(javax.xml.bind.annotation.XmlElement) Dependencies(org.apache.sis.internal.metadata.Dependencies)

Example 3 with Dependencies

use of org.apache.sis.internal.metadata.Dependencies in project sis by apache.

the class DefaultContact method getPhone.

/**
 * Returns telephone numbers at which the organization or individual may be contacted.
 * This method returns the first telephone number associated to {@code TelephoneType.VOICE}
 * or {@code TelephoneType.FACSIMILE FACSIMILE}.
 *
 * @return telephone numbers at which the organization or individual may be contacted, or {@code null}.
 *
 * @deprecated As of ISO 19115:2014, replaced by {@link #getPhones()}.
 */
@Override
@Deprecated
@Dependencies("getPhones")
@XmlElement(name = "phone", namespace = LegacyNamespaces.GMD)
public Telephone getPhone() {
    Telephone phone = null;
    if (FilterByVersion.LEGACY_METADATA.accept()) {
        final Collection<Telephone> phones = getPhones();
        if (phones != null) {
            // May be null on marshalling.
            CodeList<?> ignored = null;
            for (final Telephone c : phones) {
                if (c instanceof DefaultTelephone) {
                    String name;
                    final CodeList<?> type = ((DefaultTelephone) c).numberType;
                    if (type != null && ("VOICE".equals(name = type.name()) || "FACSIMILE".equals(name))) {
                        if (phone == null) {
                            phone = c;
                        }
                    } else if (ignored == null) {
                        ignored = type;
                    }
                }
            }
            if (ignored != null) {
                Context.warningOccured(Context.current(), DefaultContact.class, "getPhone", Messages.class, Messages.Keys.IgnoredPropertyAssociatedTo_1, ignored);
            }
        }
    }
    return phone;
}
Also used : Telephone(org.opengis.metadata.citation.Telephone) InternationalString(org.opengis.util.InternationalString) XmlElement(javax.xml.bind.annotation.XmlElement) Dependencies(org.apache.sis.internal.metadata.Dependencies)

Example 4 with Dependencies

use of org.apache.sis.internal.metadata.Dependencies in project sis by apache.

the class DefaultSource method getSourceExtents.

/**
 * Returns the information about the spatial, vertical and temporal extent of the source data.
 * This method fetches the values from the {@linkplain #getScope() scope}.
 *
 * @return information about the extent of the source data.
 *
 * @deprecated As of ISO 19115:2014, moved to {@link DefaultScope#getExtents()}.
 */
@Override
@Deprecated
@Dependencies("getScope")
@XmlElement(name = "sourceExtent", namespace = LegacyNamespaces.GMD)
public Collection<Extent> getSourceExtents() {
    if (FilterByVersion.LEGACY_METADATA.accept()) {
        Scope scope = getScope();
        if (!(scope instanceof DefaultScope)) {
            if (isModifiable()) {
                scope = new DefaultScope(scope);
                this.scope = scope;
            } else {
                return Collections.singleton(scope.getExtent());
            }
        }
    }
    return null;
}
Also used : DefaultScope(org.apache.sis.metadata.iso.maintenance.DefaultScope) Scope(org.opengis.metadata.quality.Scope) MD_Scope(org.apache.sis.internal.jaxb.metadata.MD_Scope) DefaultScope(org.apache.sis.metadata.iso.maintenance.DefaultScope) XmlElement(javax.xml.bind.annotation.XmlElement) Dependencies(org.apache.sis.internal.metadata.Dependencies)

Example 5 with Dependencies

use of org.apache.sis.internal.metadata.Dependencies in project sis by apache.

the class Dispatcher method fetchValue.

/**
 * Gets, computes or read from the database a metadata property value.
 * This method returns the first non-null value in the following choices:
 *
 * <ol>
 *   <li>If the property value is present in the {@linkplain #cache}, the cached value.</li>
 *   <li>If the "cache" can compute the value from other property values, the result of that computation.
 *       This case happen mostly for deprecated properties that are replaced by one or more newer properties.</li>
 *   <li>The value stored in the database. The database is queried only once for the requested property
 *       and the result is cached for future reuse.</li>
 * </ol>
 *
 * @param  info    information related to the <em>interface</em> of the metadata object for which a property
 *                 value is requested. This is used for fetching information from the {@link MetadataStandard}.
 * @param  method  the method to be invoked. The class given by {@link Method#getDeclaringClass()} is usually
 *                 the same than the one given by {@link LookupInfo#getMetadataType()}, but not necessarily.
 *                 The two classes may differ if the method is declared only in the implementation class.
 * @return the property value, or {@code null} if none.
 * @throws ReflectiveOperationException if an error occurred while querying the {@link #cache}.
 * @throws SQLException if an error occurred while querying the database.
 * @throws MetadataStoreException if a value was not found or can not be converted to the expected type.
 */
private Object fetchValue(final LookupInfo info, final Method method) throws ReflectiveOperationException, SQLException, MetadataStoreException {
    Object value = null;
    // Okay even if overflow.
    final long nullBit = 1L << info.asIndexMap(source.standard).get(method.getName());
    /*
         * The NULL_COLLECTION semaphore prevents creation of new empty collections by getter methods
         * (a consequence of lazy instantiation). The intent is to avoid creation of unnecessary objects
         * for all unused properties. Users should not see behavioral difference.
         */
    if ((nullValues & nullBit) == 0) {
        final Class<?> type = info.getMetadataType();
        final boolean allowNull = Semaphores.queryAndSet(Semaphores.NULL_COLLECTION);
        try {
            Object cache = this.cache;
            if (cache != null) {
                synchronized (cache) {
                    value = method.invoke(cache);
                }
            }
            if (value == null) {
                // Precaution in case method.invoke(cache) fetched other metadata.
                info.setMetadataType(type);
                value = source.readColumn(info, method, this);
                if (value != null) {
                    if (cache == null) {
                        final Class<?> impl = source.standard.getImplementation(type);
                        if (impl == null) {
                            return value;
                        }
                        this.cache = cache = impl.newInstance();
                    /*
                             * We do not use AtomicReference because it is okay if the cache is instantiated twice.
                             * It would cause us to query the database twice, but we should get the same information.
                             */
                    }
                    final Map<String, Object> map = source.standard.asValueMap(cache, type, KeyNamePolicy.METHOD_NAME, ValueExistencePolicy.ALL);
                    synchronized (cache) {
                        value = map.putIfAbsent(method.getName(), value);
                        if (value == null) {
                            value = method.invoke(cache);
                        }
                    }
                } else {
                    /*
                         * If we found no explicit value for the requested property, maybe it is a deprecated property
                         * computed from other property values and those other properties have not yet been stored in
                         * the cache object (because that "cache" is also the object computing deprecated properties).
                         */
                    final Class<?> impl = source.standard.getImplementation(type);
                    if (impl != null) {
                        final Dependencies dependencies = impl.getMethod(method.getName()).getAnnotation(Dependencies.class);
                        if (dependencies != null) {
                            boolean hasValue = false;
                            for (final String dep : dependencies.value()) {
                                info.setMetadataType(type);
                                hasValue |= (fetchValue(info, impl.getMethod(dep)) != null);
                            }
                            if (hasValue) {
                                // Created by recursive 'invoke(…)' call above.
                                cache = this.cache;
                                if (cache != null) {
                                    synchronized (cache) {
                                        // Attempt a new computation.
                                        value = method.invoke(cache);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } finally {
            if (!allowNull) {
                Semaphores.clear(Semaphores.NULL_COLLECTION);
            }
        }
    }
    if (value == null) {
        nullValues |= nullBit;
    }
    return value;
}
Also used : Dependencies(org.apache.sis.internal.metadata.Dependencies)

Aggregations

Dependencies (org.apache.sis.internal.metadata.Dependencies)5 XmlElement (javax.xml.bind.annotation.XmlElement)3 InternationalString (org.opengis.util.InternationalString)2 Method (java.lang.reflect.Method)1 URI (java.net.URI)1 CI_Citation (org.apache.sis.internal.jaxb.metadata.CI_Citation)1 MD_Scope (org.apache.sis.internal.jaxb.metadata.MD_Scope)1 DefaultCitation (org.apache.sis.metadata.iso.citation.DefaultCitation)1 DefaultOnlineResource (org.apache.sis.metadata.iso.citation.DefaultOnlineResource)1 AbstractIdentification (org.apache.sis.metadata.iso.identification.AbstractIdentification)1 DefaultDataIdentification (org.apache.sis.metadata.iso.identification.DefaultDataIdentification)1 DefaultScope (org.apache.sis.metadata.iso.maintenance.DefaultScope)1 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)1 Test (org.junit.Test)1 Citation (org.opengis.metadata.citation.Citation)1 OnlineResource (org.opengis.metadata.citation.OnlineResource)1 Telephone (org.opengis.metadata.citation.Telephone)1 Identification (org.opengis.metadata.identification.Identification)1 Scope (org.opengis.metadata.quality.Scope)1