1 /*
   2  * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.imageio.metadata;
  27 
  28 import org.w3c.dom.Node;
  29 import java.lang.reflect.Method;
  30 
  31 /**
  32  * An abstract class to be extended by objects that represent metadata
  33  * (non-image data) associated with images and streams.  Plug-ins
  34  * represent metadata using opaque, plug-in specific objects.  These
  35  * objects, however, provide the ability to access their internal
  36  * information as a tree of <code>IIOMetadataNode</code> objects that
  37  * support the XML DOM interfaces as well as additional interfaces for
  38  * storing non-textual data and retrieving information about legal
  39  * data values.  The format of such trees is plug-in dependent, but
  40  * plug-ins may choose to support a plug-in neutral format described
  41  * below.  A single plug-in may support multiple metadata formats,
  42  * whose names maybe determined by calling
  43  * <code>getMetadataFormatNames</code>.  The plug-in may also support
  44  * a single special format, referred to as the "native" format, which
  45  * is designed to encode its metadata losslessly.  This format will
  46  * typically be designed specifically to work with a specific file
  47  * format, so that images may be loaded and saved in the same format
  48  * with no loss of metadata, but may be less useful for transferring
  49  * metadata between an <code>ImageReader</code> and an
  50  * <code>ImageWriter</code> for different image formats.  To convert
  51  * between two native formats as losslessly as the image file formats
  52  * will allow, an <code>ImageTranscoder</code> object must be used.
  53  *
  54  * @see javax.imageio.ImageReader#getImageMetadata
  55  * @see javax.imageio.ImageReader#getStreamMetadata
  56  * @see javax.imageio.ImageReader#readAll
  57  * @see javax.imageio.ImageWriter#getDefaultStreamMetadata
  58  * @see javax.imageio.ImageWriter#getDefaultImageMetadata
  59  * @see javax.imageio.ImageWriter#write
  60  * @see javax.imageio.ImageWriter#convertImageMetadata
  61  * @see javax.imageio.ImageWriter#convertStreamMetadata
  62  * @see javax.imageio.IIOImage
  63  * @see javax.imageio.ImageTranscoder
  64  *
  65  */
  66 public abstract class IIOMetadata {
  67 
  68     /**
  69      * A boolean indicating whether the concrete subclass supports the
  70      * standard metadata format, set via the constructor.
  71      */
  72     protected boolean standardFormatSupported;
  73 
  74     /**
  75      * The name of the native metadata format for this object,
  76      * initialized to <code>null</code> and set via the constructor.
  77      */
  78     protected String nativeMetadataFormatName = null;
  79 
  80     /**
  81      * The name of the class implementing <code>IIOMetadataFormat</code>
  82      * and representing the native metadata format, initialized to
  83      * <code>null</code> and set via the constructor.
  84      */
  85     protected String nativeMetadataFormatClassName = null;
  86 
  87     /**
  88      * An array of names of formats, other than the standard and
  89      * native formats, that are supported by this plug-in,
  90      * initialized to <code>null</code> and set via the constructor.
  91      */
  92     protected String[] extraMetadataFormatNames = null;
  93 
  94     /**
  95      * An array of names of classes implementing <code>IIOMetadataFormat</code>
  96      * and representing the metadata formats, other than the standard and
  97      * native formats, that are supported by this plug-in,
  98      * initialized to <code>null</code> and set via the constructor.
  99      */
 100     protected String[] extraMetadataFormatClassNames = null;
 101 
 102     /**
 103      * An <code>IIOMetadataController</code> that is suggested for use
 104      * as the controller for this <code>IIOMetadata</code> object.  It
 105      * may be retrieved via <code>getDefaultController</code>.  To
 106      * install the default controller, call
 107      * <code>setController(getDefaultController())</code>.  This
 108      * instance variable should be set by subclasses that choose to
 109      * provide their own default controller, usually a GUI, for
 110      * setting parameters.
 111      *
 112      * @see IIOMetadataController
 113      * @see #getDefaultController
 114      */
 115     protected IIOMetadataController defaultController = null;
 116 
 117     /**
 118      * The <code>IIOMetadataController</code> that will be
 119      * used to provide settings for this <code>IIOMetadata</code>
 120      * object when the <code>activateController</code> method
 121      * is called.  This value overrides any default controller,
 122      * even when <code>null</code>.
 123      *
 124      * @see IIOMetadataController
 125      * @see #setController(IIOMetadataController)
 126      * @see #hasController()
 127      * @see #activateController()
 128      */
 129     protected IIOMetadataController controller = null;
 130 
 131     /**
 132      * Constructs an empty <code>IIOMetadata</code> object.  The
 133      * subclass is responsible for supplying values for all protected
 134      * instance variables that will allow any non-overridden default
 135      * implementations of methods to satisfy their contracts.  For example,
 136      * <code>extraMetadataFormatNames</code> should not have length 0.
 137      */
 138     protected IIOMetadata() {}
 139 
 140     /**
 141      * Constructs an <code>IIOMetadata</code> object with the given
 142      * format names and format class names, as well as a boolean
 143      * indicating whether the standard format is supported.
 144      *
 145      * <p> This constructor does not attempt to check the class names
 146      * for validity.  Invalid class names may cause exceptions in
 147      * subsequent calls to <code>getMetadataFormat</code>.
 148      *
 149      * @param standardMetadataFormatSupported <code>true</code> if
 150      * this object can return or accept a DOM tree using the standard
 151      * metadata format.
 152      * @param nativeMetadataFormatName the name of the native metadata
 153      * format, as a <code>String</code>, or <code>null</code> if there
 154      * is no native format.
 155      * @param nativeMetadataFormatClassName the name of the class of
 156      * the native metadata format, or <code>null</code> if there is
 157      * no native format.
 158      * @param extraMetadataFormatNames an array of <code>String</code>s
 159      * indicating additional formats supported by this object, or
 160      * <code>null</code> if there are none.
 161      * @param extraMetadataFormatClassNames an array of <code>String</code>s
 162      * indicating the class names of any additional formats supported by
 163      * this object, or <code>null</code> if there are none.
 164      *
 165      * @exception IllegalArgumentException if
 166      * <code>extraMetadataFormatNames</code> has length 0.
 167      * @exception IllegalArgumentException if
 168      * <code>extraMetadataFormatNames</code> and
 169      * <code>extraMetadataFormatClassNames</code> are neither both
 170      * <code>null</code>, nor of the same length.
 171      */
 172     protected IIOMetadata(boolean standardMetadataFormatSupported,
 173                           String nativeMetadataFormatName,
 174                           String nativeMetadataFormatClassName,
 175                           String[] extraMetadataFormatNames,
 176                           String[] extraMetadataFormatClassNames) {
 177         this.standardFormatSupported = standardMetadataFormatSupported;
 178         this.nativeMetadataFormatName = nativeMetadataFormatName;
 179         this.nativeMetadataFormatClassName = nativeMetadataFormatClassName;
 180         if (extraMetadataFormatNames != null) {
 181             if (extraMetadataFormatNames.length == 0) {
 182                 throw new IllegalArgumentException
 183                     ("extraMetadataFormatNames.length == 0!");
 184             }
 185             if (extraMetadataFormatClassNames == null) {
 186                 throw new IllegalArgumentException
 187                     ("extraMetadataFormatNames != null && extraMetadataFormatClassNames == null!");
 188             }
 189             if (extraMetadataFormatClassNames.length !=
 190                 extraMetadataFormatNames.length) {
 191                 throw new IllegalArgumentException
 192                     ("extraMetadataFormatClassNames.length != extraMetadataFormatNames.length!");
 193             }
 194             this.extraMetadataFormatNames =
 195                 (String[]) extraMetadataFormatNames.clone();
 196             this.extraMetadataFormatClassNames =
 197                 (String[]) extraMetadataFormatClassNames.clone();
 198         } else {
 199             if (extraMetadataFormatClassNames != null) {
 200                 throw new IllegalArgumentException
 201                     ("extraMetadataFormatNames == null && extraMetadataFormatClassNames != null!");
 202             }
 203         }
 204     }
 205 
 206     /**
 207      * Returns <code>true</code> if the standard metadata format is
 208      * supported by <code>getMetadataFormat</code>,
 209      * <code>getAsTree</code>, <code>setFromTree</code>, and
 210      * <code>mergeTree</code>.
 211      *
 212      * <p> The default implementation returns the value of the
 213      * <code>standardFormatSupported</code> instance variable.
 214      *
 215      * @return <code>true</code> if the standard metadata format
 216      * is supported.
 217      *
 218      * @see #getAsTree
 219      * @see #setFromTree
 220      * @see #mergeTree
 221      * @see #getMetadataFormat
 222      */
 223     public boolean isStandardMetadataFormatSupported() {
 224         return standardFormatSupported;
 225     }
 226 
 227     /**
 228      * Returns <code>true</code> if this object does not support the
 229      * <code>mergeTree</code>, <code>setFromTree</code>, and
 230      * <code>reset</code> methods.
 231      *
 232      * @return true if this <code>IIOMetadata</code> object cannot be
 233      * modified.
 234      */
 235     public abstract boolean isReadOnly();
 236 
 237     /**
 238      * Returns the name of the "native" metadata format for this
 239      * plug-in, which typically allows for lossless encoding and
 240      * transmission of the metadata stored in the format handled by
 241      * this plug-in.  If no such format is supported,
 242      * <code>null</code>will be returned.
 243      *
 244      * <p> The structure and contents of the "native" metadata format
 245      * are defined by the plug-in that created this
 246      * <code>IIOMetadata</code> object.  Plug-ins for simple formats
 247      * will usually create a dummy node for the root, and then a
 248      * series of child nodes representing individual tags, chunks, or
 249      * keyword/value pairs.  A plug-in may choose whether or not to
 250      * document its native format.
 251      *
 252      * <p> The default implementation returns the value of the
 253      * <code>nativeMetadataFormatName</code> instance variable.
 254      *
 255      * @return the name of the native format, or <code>null</code>.
 256      *
 257      * @see #getExtraMetadataFormatNames
 258      * @see #getMetadataFormatNames
 259      */
 260     public String getNativeMetadataFormatName() {
 261         return nativeMetadataFormatName;
 262     }
 263 
 264     /**
 265      * Returns an array of <code>String</code>s containing the names
 266      * of additional metadata formats, other than the native and standard
 267      * formats, recognized by this plug-in's
 268      * <code>getAsTree</code>, <code>setFromTree</code>, and
 269      * <code>mergeTree</code> methods.  If there are no such additional
 270      * formats, <code>null</code> is returned.
 271      *
 272      * <p> The default implementation returns a clone of the
 273      * <code>extraMetadataFormatNames</code> instance variable.
 274      *
 275      * @return an array of <code>String</code>s with length at least
 276      * 1, or <code>null</code>.
 277      *
 278      * @see #getAsTree
 279      * @see #setFromTree
 280      * @see #mergeTree
 281      * @see #getNativeMetadataFormatName
 282      * @see #getMetadataFormatNames
 283      */
 284     public String[] getExtraMetadataFormatNames() {
 285         if (extraMetadataFormatNames == null) {
 286             return null;
 287         }
 288         return (String[])extraMetadataFormatNames.clone();
 289     }
 290 
 291     /**
 292      * Returns an array of <code>String</code>s containing the names
 293      * of all metadata formats, including the native and standard
 294      * formats, recognized by this plug-in's <code>getAsTree</code>,
 295      * <code>setFromTree</code>, and <code>mergeTree</code> methods.
 296      * If there are no such formats, <code>null</code> is returned.
 297      *
 298      * <p> The default implementation calls
 299      * <code>getNativeMetadataFormatName</code>,
 300      * <code>isStandardMetadataFormatSupported</code>, and
 301      * <code>getExtraMetadataFormatNames</code> and returns the
 302      * combined results.
 303      *
 304      * @return an array of <code>String</code>s.
 305      *
 306      * @see #getNativeMetadataFormatName
 307      * @see #isStandardMetadataFormatSupported
 308      * @see #getExtraMetadataFormatNames
 309      */
 310     public String[] getMetadataFormatNames() {
 311         String nativeName = getNativeMetadataFormatName();
 312         String standardName = isStandardMetadataFormatSupported() ?
 313             IIOMetadataFormatImpl.standardMetadataFormatName : null;
 314         String[] extraNames = getExtraMetadataFormatNames();
 315 
 316         int numFormats = 0;
 317         if (nativeName != null) {
 318             ++numFormats;
 319         }
 320         if (standardName != null) {
 321             ++numFormats;
 322         }
 323         if (extraNames != null) {
 324             numFormats += extraNames.length;
 325         }
 326         if (numFormats == 0) {
 327             return null;
 328         }
 329 
 330         String[] formats = new String[numFormats];
 331         int index = 0;
 332         if (nativeName != null) {
 333             formats[index++] = nativeName;
 334         }
 335         if (standardName != null) {
 336             formats[index++] = standardName;
 337         }
 338         if (extraNames != null) {
 339             for (int i = 0; i < extraNames.length; i++) {
 340                 formats[index++] = extraNames[i];
 341             }
 342         }
 343 
 344         return formats;
 345     }
 346 
 347     /**
 348      * Returns an <code>IIOMetadataFormat</code> object describing the
 349      * given metadata format, or <code>null</code> if no description
 350      * is available.  The supplied name must be one of those returned
 351      * by <code>getMetadataFormatNames</code> (<i>i.e.</i>, either the
 352      * native format name, the standard format name, or one of those
 353      * returned by <code>getExtraMetadataFormatNames</code>).
 354      *
 355      * <p> The default implementation checks the name against the
 356      * global standard metadata format name, and returns that format
 357      * if it is supported.  Otherwise, it checks against the native
 358      * format names followed by any additional format names.  If a
 359      * match is found, it retrieves the name of the
 360      * <code>IIOMetadataFormat</code> class from
 361      * <code>nativeMetadataFormatClassName</code> or
 362      * <code>extraMetadataFormatClassNames</code> as appropriate, and
 363      * constructs an instance of that class using its
 364      * <code>getInstance</code> method.
 365      *
 366      * @param formatName the desired metadata format.
 367      *
 368      * @return an <code>IIOMetadataFormat</code> object.
 369      *
 370      * @exception IllegalArgumentException if <code>formatName</code>
 371      * is <code>null</code> or is not one of the names recognized by
 372      * the plug-in.
 373      * @exception IllegalStateException if the class corresponding to
 374      * the format name cannot be loaded.
 375      */
 376     public IIOMetadataFormat getMetadataFormat(String formatName) {
 377         if (formatName == null) {
 378             throw new IllegalArgumentException("formatName == null!");
 379         }
 380         if (standardFormatSupported
 381             && formatName.equals
 382                 (IIOMetadataFormatImpl.standardMetadataFormatName)) {
 383             return IIOMetadataFormatImpl.getStandardFormatInstance();
 384         }
 385         String formatClassName = null;
 386         if (formatName.equals(nativeMetadataFormatName)) {
 387             formatClassName = nativeMetadataFormatClassName;
 388         } else if (extraMetadataFormatNames != null) {
 389             for (int i = 0; i < extraMetadataFormatNames.length; i++) {
 390                 if (formatName.equals(extraMetadataFormatNames[i])) {
 391                     formatClassName = extraMetadataFormatClassNames[i];
 392                     break;  // out of for
 393                 }
 394             }
 395         }
 396         if (formatClassName == null) {
 397             throw new IllegalArgumentException("Unsupported format name");
 398         }
 399         try {
 400             Class cls = null;
 401             final Object o = this;
 402 
 403             // firstly we try to use classloader used for loading
 404             // the IIOMetadata implemantation for this plugin.
 405             ClassLoader loader = (ClassLoader)
 406                 java.security.AccessController.doPrivileged(
 407                     new java.security.PrivilegedAction() {
 408                             public Object run() {
 409                                 return o.getClass().getClassLoader();
 410                             }
 411                         });
 412 
 413             try {
 414                 cls = Class.forName(formatClassName, true,
 415                                     loader);
 416             } catch (ClassNotFoundException e) {
 417                 // we failed to load IIOMetadataFormat class by
 418                 // using IIOMetadata classloader.Next try is to
 419                 // use thread context classloader.
 420                 loader = (ClassLoader)
 421                     java.security.AccessController.doPrivileged(
 422                         new java.security.PrivilegedAction() {
 423                                 public Object run() {
 424                                     return Thread.currentThread().getContextClassLoader();
 425                                 }
 426                         });
 427                 try {
 428                     cls = Class.forName(formatClassName, true,
 429                                         loader);
 430                 } catch (ClassNotFoundException e1) {
 431                     // finally we try to use system classloader in case
 432                     // if we failed to load IIOMetadataFormat implementation
 433                     // class above.
 434                     cls = Class.forName(formatClassName, true,
 435                                         ClassLoader.getSystemClassLoader());
 436                 }
 437             }
 438 
 439             Method meth = cls.getMethod("getInstance");
 440             return (IIOMetadataFormat) meth.invoke(null);
 441         } catch (Exception e) {
 442             RuntimeException ex =
 443                 new IllegalStateException ("Can't obtain format");
 444             ex.initCause(e);
 445             throw ex;
 446         }
 447 
 448     }
 449 
 450     /**
 451      * Returns an XML DOM <code>Node</code> object that represents the
 452      * root of a tree of metadata contained within this object
 453      * according to the conventions defined by a given metadata
 454      * format.
 455      *
 456      * <p> The names of the available metadata formats may be queried
 457      * using the <code>getMetadataFormatNames</code> method.
 458      *
 459      * @param formatName the desired metadata format.
 460      *
 461      * @return an XML DOM <code>Node</code> object forming the
 462      * root of a tree.
 463      *
 464      * @exception IllegalArgumentException if <code>formatName</code>
 465      * is <code>null</code> or is not one of the names returned by
 466      * <code>getMetadataFormatNames</code>.
 467      *
 468      * @see #getMetadataFormatNames
 469      * @see #setFromTree
 470      * @see #mergeTree
 471      */
 472     public abstract Node getAsTree(String formatName);
 473 
 474     /**
 475      * Alters the internal state of this <code>IIOMetadata</code>
 476      * object from a tree of XML DOM <code>Node</code>s whose syntax
 477      * is defined by the given metadata format.  The previous state is
 478      * altered only as necessary to accommodate the nodes that are
 479      * present in the given tree.  If the tree structure or contents
 480      * are invalid, an <code>IIOInvalidTreeException</code> will be
 481      * thrown.
 482      *
 483      * <p> As the semantics of how a tree or subtree may be merged with
 484      * another tree are completely format-specific, plug-in authors may
 485      * implement this method in whatever manner is most appropriate for
 486      * the format, including simply replacing all existing state with the
 487      * contents of the given tree.
 488      *
 489      * @param formatName the desired metadata format.
 490      * @param root an XML DOM <code>Node</code> object forming the
 491      * root of a tree.
 492      *
 493      * @exception IllegalStateException if this object is read-only.
 494      * @exception IllegalArgumentException if <code>formatName</code>
 495      * is <code>null</code> or is not one of the names returned by
 496      * <code>getMetadataFormatNames</code>.
 497      * @exception IllegalArgumentException if <code>root</code> is
 498      * <code>null</code>.
 499      * @exception IIOInvalidTreeException if the tree cannot be parsed
 500      * successfully using the rules of the given format.
 501      *
 502      * @see #getMetadataFormatNames
 503      * @see #getAsTree
 504      * @see #setFromTree
 505      */
 506     public abstract void mergeTree(String formatName, Node root)
 507         throws IIOInvalidTreeException;
 508 
 509     /**
 510      * Returns an <code>IIOMetadataNode</code> representing the chroma
 511      * information of the standard <code>javax_imageio_1.0</code>
 512      * metadata format, or <code>null</code> if no such information is
 513      * available.  This method is intended to be called by the utility
 514      * routine <code>getStandardTree</code>.
 515      *
 516      * <p> The default implementation returns <code>null</code>.
 517      *
 518      * <p> Subclasses should override this method to produce an
 519      * appropriate subtree if they wish to support the standard
 520      * metadata format.
 521      *
 522      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 523      *
 524      * @see #getStandardTree
 525      */
 526     protected IIOMetadataNode getStandardChromaNode() {
 527         return null;
 528     }
 529 
 530     /**
 531      * Returns an <code>IIOMetadataNode</code> representing the
 532      * compression information of the standard
 533      * <code>javax_imageio_1.0</code> metadata format, or
 534      * <code>null</code> if no such information is available.  This
 535      * method is intended to be called by the utility routine
 536      * <code>getStandardTree</code>.
 537      *
 538      * <p> The default implementation returns <code>null</code>.
 539      *
 540      * <p> Subclasses should override this method to produce an
 541      * appropriate subtree if they wish to support the standard
 542      * metadata format.
 543      *
 544      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 545      *
 546      * @see #getStandardTree
 547      */
 548     protected IIOMetadataNode getStandardCompressionNode() {
 549         return null;
 550     }
 551 
 552     /**
 553      * Returns an <code>IIOMetadataNode</code> representing the data
 554      * format information of the standard
 555      * <code>javax_imageio_1.0</code> metadata format, or
 556      * <code>null</code> if no such information is available.  This
 557      * method is intended to be called by the utility routine
 558      * <code>getStandardTree</code>.
 559      *
 560      * <p> The default implementation returns <code>null</code>.
 561      *
 562      * <p> Subclasses should override this method to produce an
 563      * appropriate subtree if they wish to support the standard
 564      * metadata format.
 565      *
 566      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 567      *
 568      * @see #getStandardTree
 569      */
 570     protected IIOMetadataNode getStandardDataNode() {
 571         return null;
 572     }
 573 
 574     /**
 575      * Returns an <code>IIOMetadataNode</code> representing the
 576      * dimension information of the standard
 577      * <code>javax_imageio_1.0</code> metadata format, or
 578      * <code>null</code> if no such information is available.  This
 579      * method is intended to be called by the utility routine
 580      * <code>getStandardTree</code>.
 581      *
 582      * <p> The default implementation returns <code>null</code>.
 583      *
 584      * <p> Subclasses should override this method to produce an
 585      * appropriate subtree if they wish to support the standard
 586      * metadata format.
 587      *
 588      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 589      *
 590      * @see #getStandardTree
 591      */
 592     protected IIOMetadataNode getStandardDimensionNode() {
 593         return null;
 594     }
 595 
 596     /**
 597      * Returns an <code>IIOMetadataNode</code> representing the document
 598      * information of the standard <code>javax_imageio_1.0</code>
 599      * metadata format, or <code>null</code> if no such information is
 600      * available.  This method is intended to be called by the utility
 601      * routine <code>getStandardTree</code>.
 602      *
 603      * <p> The default implementation returns <code>null</code>.
 604      *
 605      * <p> Subclasses should override this method to produce an
 606      * appropriate subtree if they wish to support the standard
 607      * metadata format.
 608      *
 609      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 610      *
 611      * @see #getStandardTree
 612      */
 613     protected IIOMetadataNode getStandardDocumentNode() {
 614         return null;
 615     }
 616 
 617     /**
 618      * Returns an <code>IIOMetadataNode</code> representing the textual
 619      * information of the standard <code>javax_imageio_1.0</code>
 620      * metadata format, or <code>null</code> if no such information is
 621      * available.  This method is intended to be called by the utility
 622      * routine <code>getStandardTree</code>.
 623      *
 624      * <p> The default implementation returns <code>null</code>.
 625      *
 626      * <p> Subclasses should override this method to produce an
 627      * appropriate subtree if they wish to support the standard
 628      * metadata format.
 629      *
 630      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 631      *
 632      * @see #getStandardTree
 633      */
 634     protected IIOMetadataNode getStandardTextNode() {
 635         return null;
 636     }
 637 
 638     /**
 639      * Returns an <code>IIOMetadataNode</code> representing the tiling
 640      * information of the standard <code>javax_imageio_1.0</code>
 641      * metadata format, or <code>null</code> if no such information is
 642      * available.  This method is intended to be called by the utility
 643      * routine <code>getStandardTree</code>.
 644      *
 645      * <p> The default implementation returns <code>null</code>.
 646      *
 647      * <p> Subclasses should override this method to produce an
 648      * appropriate subtree if they wish to support the standard
 649      * metadata format.
 650      *
 651      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 652      *
 653      * @see #getStandardTree
 654      */
 655     protected IIOMetadataNode getStandardTileNode() {
 656         return null;
 657     }
 658 
 659     /**
 660      * Returns an <code>IIOMetadataNode</code> representing the
 661      * transparency information of the standard
 662      * <code>javax_imageio_1.0</code> metadata format, or
 663      * <code>null</code> if no such information is available.  This
 664      * method is intended to be called by the utility routine
 665      * <code>getStandardTree</code>.
 666      *
 667      * <p> The default implementation returns <code>null</code>.
 668      *
 669      * <p> Subclasses should override this method to produce an
 670      * appropriate subtree if they wish to support the standard
 671      * metadata format.
 672      *
 673      * @return an <code>IIOMetadataNode</code>, or <code>null</code>.
 674      */
 675     protected IIOMetadataNode getStandardTransparencyNode() {
 676         return null;
 677     }
 678 
 679     /**
 680      * Appends a new node to an existing node, if the new node is
 681      * non-<code>null</code>.
 682      */
 683     private void append(IIOMetadataNode root, IIOMetadataNode node) {
 684         if (node != null) {
 685             root.appendChild(node);
 686         }
 687     }
 688 
 689     /**
 690      * A utility method to return a tree of
 691      * <code>IIOMetadataNode</code>s representing the metadata
 692      * contained within this object according to the conventions of
 693      * the standard <code>javax_imageio_1.0</code> metadata format.
 694      *
 695      * <p> This method calls the various <code>getStandard*Node</code>
 696      * methods to supply each of the subtrees rooted at the children
 697      * of the root node.  If any of those methods returns
 698      * <code>null</code>, the corresponding subtree will be omitted.
 699      * If all of them return <code>null</code>, a tree consisting of a
 700      * single root node will be returned.
 701      *
 702      * @return an <code>IIOMetadataNode</code> representing the root
 703      * of a metadata tree in the <code>javax_imageio_1.0</code>
 704      * format.
 705      *
 706      * @see #getStandardChromaNode
 707      * @see #getStandardCompressionNode
 708      * @see #getStandardDataNode
 709      * @see #getStandardDimensionNode
 710      * @see #getStandardDocumentNode
 711      * @see #getStandardTextNode
 712      * @see #getStandardTileNode
 713      * @see #getStandardTransparencyNode
 714      */
 715     protected final IIOMetadataNode getStandardTree() {
 716         IIOMetadataNode root = new IIOMetadataNode
 717                 (IIOMetadataFormatImpl.standardMetadataFormatName);
 718         append(root, getStandardChromaNode());
 719         append(root, getStandardCompressionNode());
 720         append(root, getStandardDataNode());
 721         append(root, getStandardDimensionNode());
 722         append(root, getStandardDocumentNode());
 723         append(root, getStandardTextNode());
 724         append(root, getStandardTileNode());
 725         append(root, getStandardTransparencyNode());
 726         return root;
 727     }
 728 
 729     /**
 730      * Sets the internal state of this <code>IIOMetadata</code> object
 731      * from a tree of XML DOM <code>Node</code>s whose syntax is
 732      * defined by the given metadata format.  The previous state is
 733      * discarded.  If the tree's structure or contents are invalid, an
 734      * <code>IIOInvalidTreeException</code> will be thrown.
 735      *
 736      * <p> The default implementation calls <code>reset</code>
 737      * followed by <code>mergeTree(formatName, root)</code>.
 738      *
 739      * @param formatName the desired metadata format.
 740      * @param root an XML DOM <code>Node</code> object forming the
 741      * root of a tree.
 742      *
 743      * @exception IllegalStateException if this object is read-only.
 744      * @exception IllegalArgumentException if <code>formatName</code>
 745      * is <code>null</code> or is not one of the names returned by
 746      * <code>getMetadataFormatNames</code>.
 747      * @exception IllegalArgumentException if <code>root</code> is
 748      * <code>null</code>.
 749      * @exception IIOInvalidTreeException if the tree cannot be parsed
 750      * successfully using the rules of the given format.
 751      *
 752      * @see #getMetadataFormatNames
 753      * @see #getAsTree
 754      * @see #mergeTree
 755      */
 756     public void setFromTree(String formatName, Node root)
 757         throws IIOInvalidTreeException {
 758         reset();
 759         mergeTree(formatName, root);
 760     }
 761 
 762     /**
 763      * Resets all the data stored in this object to default values,
 764      * usually to the state this object was in immediately after
 765      * construction, though the precise semantics are plug-in specific.
 766      * Note that there are many possible default values, depending on
 767      * how the object was created.
 768      *
 769      * @exception IllegalStateException if this object is read-only.
 770      *
 771      * @see javax.imageio.ImageReader#getStreamMetadata
 772      * @see javax.imageio.ImageReader#getImageMetadata
 773      * @see javax.imageio.ImageWriter#getDefaultStreamMetadata
 774      * @see javax.imageio.ImageWriter#getDefaultImageMetadata
 775      */
 776     public abstract void reset();
 777 
 778     /**
 779      * Sets the <code>IIOMetadataController</code> to be used
 780      * to provide settings for this <code>IIOMetadata</code>
 781      * object when the <code>activateController</code> method
 782      * is called, overriding any default controller.  If the
 783      * argument is <code>null</code>, no controller will be
 784      * used, including any default.  To restore the default, use
 785      * <code>setController(getDefaultController())</code>.
 786      *
 787      * <p> The default implementation sets the <code>controller</code>
 788      * instance variable to the supplied value.
 789      *
 790      * @param controller An appropriate
 791      * <code>IIOMetadataController</code>, or <code>null</code>.
 792      *
 793      * @see IIOMetadataController
 794      * @see #getController
 795      * @see #getDefaultController
 796      * @see #hasController
 797      * @see #activateController()
 798      */
 799     public void setController(IIOMetadataController controller) {
 800         this.controller = controller;
 801     }
 802 
 803     /**
 804      * Returns whatever <code>IIOMetadataController</code> is currently
 805      * installed.  This could be the default if there is one,
 806      * <code>null</code>, or the argument of the most recent call
 807      * to <code>setController</code>.
 808      *
 809      * <p> The default implementation returns the value of the
 810      * <code>controller</code> instance variable.
 811      *
 812      * @return the currently installed
 813      * <code>IIOMetadataController</code>, or <code>null</code>.
 814      *
 815      * @see IIOMetadataController
 816      * @see #setController
 817      * @see #getDefaultController
 818      * @see #hasController
 819      * @see #activateController()
 820      */
 821     public IIOMetadataController getController() {
 822         return controller;
 823     }
 824 
 825     /**
 826      * Returns the default <code>IIOMetadataController</code>, if there
 827      * is one, regardless of the currently installed controller.  If
 828      * there is no default controller, returns <code>null</code>.
 829      *
 830      * <p> The default implementation returns the value of the
 831      * <code>defaultController</code> instance variable.
 832      *
 833      * @return the default <code>IIOMetadataController</code>, or
 834      * <code>null</code>.
 835      *
 836      * @see IIOMetadataController
 837      * @see #setController(IIOMetadataController)
 838      * @see #getController
 839      * @see #hasController
 840      * @see #activateController()
 841      */
 842     public IIOMetadataController getDefaultController() {
 843         return defaultController;
 844     }
 845 
 846     /**
 847      * Returns <code>true</code> if there is a controller installed
 848      * for this <code>IIOMetadata</code> object.
 849      *
 850      * <p> The default implementation returns <code>true</code> if the
 851      * <code>getController</code> method returns a
 852      * non-<code>null</code> value.
 853      *
 854      * @return <code>true</code> if a controller is installed.
 855      *
 856      * @see IIOMetadataController
 857      * @see #setController(IIOMetadataController)
 858      * @see #getController
 859      * @see #getDefaultController
 860      * @see #activateController()
 861      */
 862     public boolean hasController() {
 863         return (getController() != null);
 864     }
 865 
 866     /**
 867      * Activates the installed <code>IIOMetadataController</code> for
 868      * this <code>IIOMetadata</code> object and returns the resulting
 869      * value.  When this method returns <code>true</code>, all values for this
 870      * <code>IIOMetadata</code> object will be ready for the next write
 871      * operation.  If <code>false</code> is
 872      * returned, no settings in this object will have been disturbed
 873      * (<i>i.e.</i>, the user canceled the operation).
 874      *
 875      * <p> Ordinarily, the controller will be a GUI providing a user
 876      * interface for a subclass of <code>IIOMetadata</code> for a
 877      * particular plug-in.  Controllers need not be GUIs, however.
 878      *
 879      * <p> The default implementation calls <code>getController</code>
 880      * and the calls <code>activate</code> on the returned object if
 881      * <code>hasController</code> returns <code>true</code>.
 882      *
 883      * @return <code>true</code> if the controller completed normally.
 884      *
 885      * @exception IllegalStateException if there is no controller
 886      * currently installed.
 887      *
 888      * @see IIOMetadataController
 889      * @see #setController(IIOMetadataController)
 890      * @see #getController
 891      * @see #getDefaultController
 892      * @see #hasController
 893      */
 894     public boolean activateController() {
 895         if (!hasController()) {
 896             throw new IllegalStateException("hasController() == false!");
 897         }
 898         return getController().activate(this);
 899     }
 900 }