001/* IIOMetadata.java --
002   Copyright (C) 2004  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.imageio.metadata;
040
041import 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 */
077public 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}