
it.tidalwave.metadata.Metadata Maven / Gradle / Ivy
/*******************************************************************************
*
* blueMarine - open source photo workflow
* =======================================
*
* Copyright (C) 2003-2009 by Fabrizio Giudici
* Project home page: http://bluemarine.tidalwave.it
*
*******************************************************************************
*
* Licensed 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.
*
*******************************************************************************
*
* $Id: Metadata.java,v 64ddf5de96db 2009/11/06 20:43:18 fabrizio $
*
******************************************************************************/
package it.tidalwave.metadata;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import org.openide.loaders.DataObject;
/*******************************************************************************
*
* This class represents a bag of metadata items for a {@link DataObject}.
* Instances of Metadata
can be achieved by asking for them to the
* object {@link Lookup} as in the following example:
*
*
* DataObject dataObject = ...;
* Metadata metadata = dataObject.getLookup().lookup(Metadata.class);
*
*
* For each dataObject
it is guaranteed that a non-null reference
* to an unique instance of Metadata
is returned (it will be empty
* if no metadata is found). Single items can be then retrieved by calling the
* {@link Metadata#findOrCreateItem(java.lang.Class, it.tidalwave.metadata.Metadata.FindOption[])
* findOrCreateItem()} method:
*
*
* MetadataItemHolder<EXIF> exifHolder = metadata.findOrCreateItem(EXIF.class);
* MetadataItemHolder<IPTC> iptcHolder = metadata.findOrCreateItem(IPTC.class);
* EXIF exif = exifHolder.get();
* IPTC iptc = iptcHolder.get();
*
*
* or, more quickly:
*
*
* EXIF exif = metadata.findOrCreateItem(EXIF.class).get();
* IPTC iptc = metadata.findOrCreateItem(IPTC.class).get();
*
*
* The {@link MetadataItemHolder} class is just a wrapper holding the real item and
* providing some additional information:
*
*
* MetadataItemHolder<EXIF> exifHolder = metadata.findOrCreateItem(EXIF.class);
* boolean available = exifHolder.isAvailable();
* Date lmt = exifHolder.getLatestModificationTime();
* String sourceName = exifHolder.getSourceName();
* String origin = exifHolder.getOrigin();
*
*
* It is guaranteed that non null
objects are always returned by
* findOrCreateItem()
; you
* must check the {@link MetadataItemHolder#isAvailable()} property to understand
* whether the object is empty or not..
*
* Multiple calls with the same class specifier are guaranteed to return the
* same instance of MetadataItemHolder
, which - in turn - will hold
* the same instance of the bean.
*
* Each object returned by the MetadataItemHolder
is guaranteed to
* implement the full Java Bean specifications (events, listeners, etc.).
*
* Note that this happens even if the original class (in the above example
* doesn't support the contract; in this case a dynamically enhanced object is
* returned, and it is guaranteed to implement the JavaBean
* interface:
*
*
* MyItem myItem = metadata.findOrCreateItem(MyItem.class).get();
* ((JavaBean)myItem).addPropertyChangeListener(...);
*
*
* As an alternate approach, you can use reflection to find and invoke methods.
*
* @author Fabrizio Giudici
* @version $Id: Metadata.java,v 64ddf5de96db 2009/11/06 20:43:18 fabrizio $
*
******************************************************************************/
public interface Metadata
{
/***************************************************************************
*
* Interface which tags all possible options for the methods
* {@link #findOrCreateItem(Class, FindOption[])} and
* {@link #findOrCreateItems(Class, FindOption[])}. Refer to the documentation of
* implementing classes for further information.
*
**************************************************************************/
public static interface FindOption
{
}
/*******************************************************************************************************************
*
* Interface which tags all possible options for the method
* {@link #storeItem(it.tidalwave.metadata.MetadataItemHolder, it.tidalwave.metadata.Metadata.StoreOption[])}.
* Refer to the documentation of implementing classes for further information.
*
******************************************************************************************************************/
public static interface StoreOption
{
}
/***************************************************************************
*
* This enumeration contains items to identify the metadata source and
* sink types.
*
**************************************************************************/
public static enum StorageType implements FindOption, StoreOption
{
/** Matches any kind of source/sink. */
ANY_TYPE
{
public boolean includes (@Nonnull final StorageType sourceType)
{
return true;
}
},
/** Matches only internal sources/sinks, typically a dedicated persistence
facility such as a database. */
INTERNAL
{
public boolean includes (@Nonnull final StorageType sourceType)
{
return sourceType == INTERNAL;
}
},
/** Matches only external sources/sinks, such as files (images or sidecar
files). */
EXTERNAL
{
public boolean includes (@Nonnull final StorageType sourceType)
{
return sourceType == EXTERNAL;
}
},
NONE
{
public boolean includes (@Nonnull final StorageType sourceType)
{
return false;
}
};
public static final StorageType DEFAULT = INTERNAL;
public abstract boolean includes (@Nonnull final StorageType sourceType);
}
/***************************************************************************
*
* This enumeration contains items to choose which policy to use when
* storing items.
*
**************************************************************************/
public static enum ReplaceOption implements Metadata.StoreOption
{
/** Means that any copy of the same metadata item (same type and origin)
should not be dropped during store. */
DONT_REPLACE,
/** Means that any copy of the same metadata item (same type and origin)
must be dropped during store. */
REPLACE
}
/***************************************************************************
*
* An option to tell the name of the origin of a datum to store.
*
**************************************************************************/
public static class OriginFilter implements StoreOption
{
@Nonnull
private final List names;
public OriginFilter (@Nonnull final String ... names)
{
this.names = Arrays.asList(names);
}
public OriginFilter (@Nonnull final Collection names)
{
this.names = new ArrayList(names);
}
public boolean matches (@Nonnull final String name)
{
return names.contains(name);
}
@Nonnull
public Set getNames()
{
return new HashSet(names);
}
@Override
@Nonnull
public String toString()
{
return String.format("OriginFilter%s", names);
}
public static final OriginFilter ANY_ORIGIN = new OriginFilter()
{
@Override
public final boolean matches (@Nonnull final String name)
{
return true;
}
@Override
@Nonnull
public Set getNames()
{
throw new RuntimeException("Don't call me");
}
@Override
@Nonnull
public String toString()
{
return "OriginFilter[ANY_ORIGIN]";
}
};
}
/***************************************************************************
*
* An option specifying a set of names for sinks. Only the sinks matching
* the given names will be used. ANY_NAME
matches all names.
*
**************************************************************************/
public static class NameFilter implements StoreOption
{
@Nonnull
private final List names;
public NameFilter (@Nonnull final String ... names)
{
this.names = Arrays.asList(names);
}
public NameFilter (@Nonnull final Collection names)
{
this.names = new ArrayList(names);
}
public boolean matches (@Nonnull final String name)
{
return names.contains(name);
}
@Override
@Nonnull
public String toString()
{
return String.format("NameFilter%s", names);
}
public static final NameFilter ANY_NAME = new NameFilter()
{
@Override
public final boolean matches (@Nonnull final String name)
{
return true;
}
@Override
@Nonnull
public String toString()
{
return "NameFilter[ANY_NAME]";
}
};
}
/***************************************************************************
*
* Returns all the supported item classes.
*
* @return the supported item classes
*
**************************************************************************/
@Nonnull
public Set> getItemClasses();
/***************************************************************************
*
* Probes the availability of the given metadata item. This method returns
* true
if the requested item has been already loaded in memory,
* false
if it hasn't and a (potentially time-expensive) search
* is needed.
*
* @param metadataItemClass the type of the item
* @param options the options (see {@link FindOption})
* @return true
if the item is available
* @throws NoSuchMetadataTypeException if the item type is not supported
*
**************************************************************************/
public boolean isItemAvailable (@Nonnull Class> metadataItemClass,
@Nonnull FindOption ... options)
throws NoSuchMetadataTypeException;
/***************************************************************************
*
* Finds a metadata item given its class or creates it if none is found.
* Items are lazily loaded the first time they are asked for. It is
* guaranteed that the same instance will be always returned for a given
* metadataItemClass
.
* If metadataItemClass
is not valid (that is, is not one of
* the supported classes, see {@link #getItemClasses()}), a
* {@link NoSuchMetadataTypeException} is thrown.
* For further information, see the comments about the {@link Metadata} class.
* If you don't want to risk blocking on this method becase the requested item
* has not been loaded yet, consider probing its availability by calling
* {@link #isItemAvailable(Class, it.tidalwave.metadata.Metadata.FindOption[])}.
* If the method returns false
, you might want to call
* findOrCreateItem()
in a background thread.
*
* @param metadataItemClass the type of the item
* @param options the options (see {@link FindOption})
* @return the item
* @throws NoSuchMetadataTypeException if the item type is not supported
*
**************************************************************************/
@Nonnull
public - MetadataItemHolder
- findOrCreateItem (@Nonnull Class
- metadataItemClass,
@Nonnull FindOption ... options)
throws NoSuchMetadataTypeException;
/***************************************************************************
*
* Finds multiple metadata item given their class or creates one if none is
* found.
* Items are returned sorted by descending last modification time.
* If
metadataItemClass
is not valid (that is, is not one of
* the provided classes, see {@link #getItemClasses()}), a
* {@link NoSuchMetadataTypeException} is thrown. Please see
* {@link #findOrCreateItem(java.lang.Class, it.tidalwave.metadata.Metadata.FindOption[])} for further information.
*
* @param metadataItemClass the type of the item
* @param options the options (see {@link FindOption})
* @return the items
* @throws NoSuchMetadataTypeException if the item type is not supported
*
**************************************************************************/
@Nonnull
public - MetadataItemHolderList
- findOrCreateItems (@Nonnull Class
- metadataItemClass,
@Nonnull FindOption ... options)
throws NoSuchMetadataTypeException;
/***************************************************************************
*
* Stores an item into the available sinks (eventually filtered by the
* options).
* If
item
is not valid (that is, is not one of
* the supported classes, see {@link #getItemClasses()}), a
* {@link NoSuchMetadataTypeException} is thrown.
*
* @param holder the item to store
* @param options the options (see {@link StoreOption})
* @return the number of successful stores
* @throws NoSuchMetadataTypeException if the item type is not supported
*
**************************************************************************/
public - int storeItem (@Nonnull MetadataItemHolder
- holder,
@Nonnull StoreOption ... options)
throws NoSuchMetadataTypeException;
/***************************************************************************
*
* Returns the bound {@link DataObject}.
*
* @return the bound object
*
**************************************************************************/
@Nonnull
public DataObject getDataObject();
/***************************************************************************
*
* Returns the latest modification time of this object. This property will
* be updated whenever a contained item is updated.
*
* @return the latest modification time
*
**************************************************************************/
@Nonnull
public Date getLatestModificationTime();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy