package org.springframework.roo.metadata; import java.util.Set; /** * Registers the dependencies between different metadata identification strings. * <p> * Metadata is free to depend on other metadata, including both metadata classes * and metadata instances being depended on or depending on other metadata * classes and metadata instances. In other words, metadata dependency graphs * are not limited to only metadata instances. * <p> * For performance and memory efficiency reasons, only metadata identification * strings are stored by the {@link MetadataDependencyRegistry}. In particular, * {@link MetadataItem} instances are definitely not stored internally - which * is especially applicable given they are immutable. * <p> * From a logical perspective, an item of metadata can "depend on" some other * piece of metadata. For example, an item of metadata representing the members * appearing within a Java source file would "depend on" the metadata that * represents the physical source file on disk. An item of metadata can also be * "depended on" by other pieces of metadata. If the relationship just * exemplified was declared, the metadata representing the physical source file * on disk would be "depended on" by the Java member metadata. We use the terms * "upstream" and "downstream" to refer to these dependencies. In our example we * would say that Java member metadata is downstream of the physical source file * on disk metadata. We would also say that the physical source file on disk is * upstream of the Java member metadata. * <p> * In terms of notifications, the {@link MetadataDependencyRegistry} maintains a * reference to the {@link MetadataService}, and delivers notifications to the * {@link MetadataService} via its extension of the * {@link MetadataNotificationListener} interface. Note that a * {@link MetadataService} may subsequently deliver notifications to * {@link MetadataProvider}s using the semantics defined in the contract for * {@link MetadataService}. * * @author Ben Alex * @since 1.0 */ public interface MetadataDependencyRegistry { /** * Registers an additional instance to receive * {@link MetadataNotificationListener} events. Note that these events are * guaranteed to be delivered after the {@link MetadataService} has received * them. * <p> * Attempting to register a {@link MetadataService} using this method will * result in an exception. * * @param listener to also receive all notifications (required) */ void addNotificationListener(MetadataNotificationListener listener); /** * Removes all upstream dependencies that were previously registered for the * specified downstream dependency. This is useful if rebuilding the * downstream dependency metadata, and just want to clear all old dependency * information from the registry. * <p> * The dependency must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. * <p> * If the dependency was never registered in the first place, this method * simply returns. * * @param downstreamDependency the downstream dependency (required) */ void deregisterDependencies(String downstreamDependency); /** * Removes a dependency between two items of metadata. * <p> * Both arguments must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. * <p> * If the dependency was never registered in the first place, this method * simply returns. * * @param upstreamDependency the upstream dependency (required) * @param downstreamDependency the downstream dependency (required) */ void deregisterDependency(String upstreamDependency, String downstreamDependency); /** * Obtains the list of the immediate downstream dependencies of the * indicated metadata item. * <p> * The upstream dependency must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. However, the * upstream dependency need not have been registered with this registry in * advance (in which case the method will not return any downstream * dependencies, as none are known). * * @param upstreamDependency to find the immediate downstream items for * (required) * @return an immutable set of dependencies (never null, but the set may be * empty) */ Set<String> getDownstream(String upstreamDependency); /** * Obtains a list of the immediate upstream dependencies of the indicated * metadata item. * <p> * The downstream dependency must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. * * @param downstreamDependency to find the immediate upstream items for * (required) * @return an immutable set of dependencies (never null, but the set may be * empty) */ Set<String> getUpstream(String downstreamDependency); /** * Indicates whether the indicated downstream dependency is legally * permitted to depend on the indicated upstream dependency. Specifically, * the {@link MetadataDependencyRegistry} is required to verify the upstream * dependency (and its dependencies) do not already depend on the downstream * dependency (or any other dependency that itself depends on the downstream * dependency). Good metadata design should prevent metadata from ever * invoking this method and receiving a false response, but we like to be * robust in ensuring the {@link MetadataDependencyRegistry} never can * represent a circular dependency graph. * <p> * Both arguments must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. * * @param upstreamDependency the upstream dependency (required; eg metadata * representing a disk file) * @param downstreamDependency the downstream dependency (required; eg * metadata representing a Java type) * @return true if the dependency relationship is legal */ boolean isValidDependency(String upstreamDependency, String downstreamDependency); /** * Causes the immediate downstream dependencies of the indicated metadata * item to be notified the upstream metadata item is publishing a * notification. * <p> * The upstream dependency must return true if presented to * {@link MetadataIdentificationUtils#isValid(String)}. However, the * upstream dependency need not have been registered with this registry in * advance (in which case the method will not notify any downstream * dependencies, as none are known). * <p> * Notifications are delivered to the {@link MetadataService} initially, * followed by all {@link MetadataNotificationListener}s registered against * the instance. * * @param upstreamDependency that is generating the notification (required). */ void notifyDownstream(String upstreamDependency); /** * Registers a dependency between two items of metadata. * <p> * The two items of metadata will be presented to * {@link #isValidDependency(String, String)}. If this method returns false, * an exception will be generated. * * @param upstreamDependency the upstream dependency (required; eg metadata * representing a disk file) * @param downstreamDependency the downstream dependency (required; eg * metadata representing a Java type) */ void registerDependency(String upstreamDependency, String downstreamDependency); /** * De-register an additional instance to receive * {@link MetadataNotificationListener} events. If the listener was never * registered in the first place, the method simply returns. * * @param listener to no longer receive notifications (required) */ void removeNotificationListener(MetadataNotificationListener listener); }