001    /* IIOMetadata.java --
002       Copyright (C) 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.imageio.metadata;
040    
041    import org.w3c.dom.Node;
042    
043    /**
044     * Represents metadata that describe an image or an image stream.
045     * Each ImageIO plugin will represent image data using an opaque
046     * object but all such objects should expose their internal
047     * information as a tree of IIOMetadataNodes.
048     *
049     * There are three formats of metadata that a plugin can support:
050     *
051     * <ul>
052     *   <li>a "native" format</li>
053     *   <li>a custom format</li>
054     *   <li>a standard plugin-neutral format</li>
055     * </ul>
056     *
057     * If a plugin supports more than one format of metadata, the other
058     * formats can be retrieved by calling getMetadataFormatNames.
059     *
060     * The native format is used to transfer metadata from one image to
061     * another image of the same type, losslessly.
062     *
063     * The custom format describes the image metadata and exposes a tree
064     * of IIOMetadataNodes but its internal representation is specific to
065     * this plugin.
066     *
067     * The plugin-neutral format uses a generic tree structure as its
068     * internal representation.
069     *
070     * ImageTranscoders may be used to convert metadata understood by one
071     * plugin to metadata understood by another, however the conversion
072     * may be lossy.
073     *
074     * @author Michael Koch (konqueror@gmx.de)
075     * @author Thomas Fitzsimmons (fitzsim@redhat.com)
076     */
077    public abstract class IIOMetadata
078    {
079      protected IIOMetadataController controller;
080      protected IIOMetadataController defaultController;
081      protected String[] extraMetadataFormatClassNames;
082      protected String[] extraMetadataFormatNames;
083      protected String nativeMetadataFormatClassName;
084      protected String nativeMetadataFormatName;
085      protected boolean standardFormatSupported;
086    
087      /**
088       * Construct an IIOMetadata object.
089       */
090      protected IIOMetadata()
091      {
092        // Do nothing here.
093      }
094    
095      /**
096       * Construct an IIOMetadata object.
097       *
098       * @param standardMetadataFormatSupported
099       * @param nativeMetadataFormatName
100       * @param nativeMetadataFormatClassName
101       * @param extraMetadataFormatNames
102       * @param extraMetadataFormatClassNames
103       *
104       * @throws IllegalArgumentException if extraMetadataFormatNames has length of
105       * zero or extraMetadataFormatNames and extraMetadataFormatClassNames are
106       * neither both null, not have the same length
107       */
108      protected IIOMetadata(boolean standardMetadataFormatSupported,
109                            String nativeMetadataFormatName,
110                            String nativeMetadataFormatClassName,
111                            String[] extraMetadataFormatNames,
112                            String[] extraMetadataFormatClassNames)
113      {
114        if (extraMetadataFormatNames != null
115            && extraMetadataFormatNames.length == 0)
116          throw new IllegalArgumentException
117            ("extraMetadataFormatNames may not be empty");
118    
119        if (((extraMetadataFormatNames == null)
120             && (extraMetadataFormatClassNames != null))
121            || ((extraMetadataFormatNames != null)
122                && (extraMetadataFormatClassNames == null))
123            || ((extraMetadataFormatNames != null)
124                && (extraMetadataFormatClassNames != null)
125                && (extraMetadataFormatNames.length !=
126                    extraMetadataFormatClassNames.length)))
127          throw new IllegalArgumentException
128            ("extraMetadataFormatNames and extraMetadataFormatClassNames " +
129             "have different lengths");
130    
131        this.standardFormatSupported = standardMetadataFormatSupported;
132        this.nativeMetadataFormatName = nativeMetadataFormatName;
133        this.nativeMetadataFormatClassName = nativeMetadataFormatClassName;
134        this.extraMetadataFormatNames = extraMetadataFormatNames;
135        this.extraMetadataFormatClassNames = extraMetadataFormatClassNames;
136      }
137    
138      public boolean activateController()
139      {
140        if (! hasController())
141          return false;
142    
143        return getDefaultController().activate(this);
144      }
145    
146      public IIOMetadataController getController()
147      {
148        return controller;
149      }
150    
151      public IIOMetadataController getDefaultController()
152      {
153        return defaultController;
154      }
155    
156      public String[] getExtraMetadataFormatNames()
157      {
158        return (String[]) extraMetadataFormatNames.clone();
159      }
160    
161      public IIOMetadataFormat getMetadataFormat(String formatName)
162      {
163        if (formatName == null)
164          throw new IllegalArgumentException("formatName may not be null");
165    
166        String formatClassName = null;
167    
168        if (isStandardMetadataFormatSupported()
169            && formatName.equals(nativeMetadataFormatName))
170          formatClassName = nativeMetadataFormatClassName;
171        else
172          {
173            String[] extraFormatNames = getExtraMetadataFormatNames();
174    
175            for (int i = extraFormatNames.length - 1; i >= 0; --i)
176              if (extraFormatNames[i].equals(formatName))
177                {
178                  formatClassName = extraFormatNames[i];
179                  break;
180                }
181          }
182    
183        if (formatClassName == null)
184          throw new IllegalArgumentException("unknown format");
185    
186        IIOMetadataFormat format;
187    
188        try
189          {
190            format = (IIOMetadataFormat) Class.forName(formatClassName)
191                                              .newInstance();
192          }
193        catch (Exception e)
194          {
195            IllegalStateException ise = new IllegalStateException();
196            ise.initCause(e);
197            throw ise;
198          }
199    
200        return format;
201      }
202    
203      public String[] getMetadataFormatNames()
204      {
205        String[] formatNames = getExtraMetadataFormatNames();
206    
207        if (isStandardMetadataFormatSupported())
208          {
209            // Combine native metadata format name and extra metadata format names
210            // into one String array.
211            String[] tmp = new String[formatNames.length + 1];
212            tmp[0] = getNativeMetadataFormatName();
213    
214            for (int i = 1; i < tmp.length; ++i)
215              tmp[i] = formatNames[i - 1];
216    
217            formatNames = tmp;
218          }
219    
220        return formatNames;
221      }
222    
223      public String getNativeMetadataFormatName()
224      {
225        return nativeMetadataFormatName;
226      }
227    
228      public boolean hasController()
229      {
230        return getController() != null;
231      }
232    
233      public abstract boolean isReadOnly();
234    
235      public boolean isStandardMetadataFormatSupported()
236      {
237        return standardFormatSupported;
238      }
239    
240      public abstract void reset();
241    
242      public void setController(IIOMetadataController controller)
243      {
244        this.controller = controller;
245      }
246    
247      public abstract Node getAsTree (String formatName);
248    
249      protected IIOMetadataNode getStandardChromaNode ()
250      {
251        return null;
252      }
253    
254      protected IIOMetadataNode getStandardCompressionNode ()
255      {
256        return null;
257      }
258    
259      protected IIOMetadataNode getStandardDataNode ()
260      {
261        return null;
262      }
263    
264      protected IIOMetadataNode getStandardDimensionNode ()
265      {
266        return null;
267      }
268    
269      protected IIOMetadataNode getStandardDocumentNode ()
270      {
271        return null;
272      }
273    
274      protected IIOMetadataNode getStandardTextNode ()
275      {
276        return null;
277      }
278    
279      protected IIOMetadataNode getStandardTileNode ()
280      {
281        return null;
282      }
283    
284      protected IIOMetadataNode getStandardTransparencyNode ()
285      {
286        return null;
287      }
288    
289      private void appendChild (IIOMetadataNode node,
290                                IIOMetadataNode child)
291      {
292        if (child != null)
293          node.appendChild(child);
294      }
295    
296      protected final IIOMetadataNode getStandardTree ()
297      {
298        IIOMetadataNode node = new IIOMetadataNode();
299    
300        appendChild (node, getStandardChromaNode());
301        appendChild (node, getStandardCompressionNode());
302        appendChild (node, getStandardDataNode());
303        appendChild (node, getStandardDimensionNode());
304        appendChild (node, getStandardDocumentNode());
305        appendChild (node, getStandardTextNode());
306        appendChild (node, getStandardTileNode());
307        appendChild (node, getStandardTransparencyNode());
308    
309        return node;
310      }
311    
312      public abstract void mergeTree (String formatName,
313                                      Node root)
314        throws IIOInvalidTreeException;
315    
316      public void setFromTree (String formatName, Node root)
317        throws IIOInvalidTreeException
318      {
319        reset();
320    
321        mergeTree (formatName, root);
322      }
323    }