Path: blob/master/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java
41153 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio.metadata;2627import org.w3c.dom.Node;2829import java.lang.reflect.Method;30import java.security.AccessController;31import java.security.PrivilegedAction;3233/**34* An abstract class to be extended by objects that represent metadata35* (non-image data) associated with images and streams. Plug-ins36* represent metadata using opaque, plug-in specific objects. These37* objects, however, provide the ability to access their internal38* information as a tree of {@code IIOMetadataNode} objects that39* support the XML DOM interfaces as well as additional interfaces for40* storing non-textual data and retrieving information about legal41* data values. The format of such trees is plug-in dependent, but42* plug-ins may choose to support a plug-in neutral format described43* below. A single plug-in may support multiple metadata formats,44* whose names maybe determined by calling45* {@code getMetadataFormatNames}. The plug-in may also support46* a single special format, referred to as the "native" format, which47* is designed to encode its metadata losslessly. This format will48* typically be designed specifically to work with a specific file49* format, so that images may be loaded and saved in the same format50* with no loss of metadata, but may be less useful for transferring51* metadata between an {@code ImageReader} and an52* {@code ImageWriter} for different image formats. To convert53* between two native formats as losslessly as the image file formats54* will allow, an {@code ImageTranscoder} object must be used.55*56* @see javax.imageio.ImageReader#getImageMetadata57* @see javax.imageio.ImageReader#getStreamMetadata58* @see javax.imageio.ImageReader#readAll59* @see javax.imageio.ImageWriter#getDefaultStreamMetadata60* @see javax.imageio.ImageWriter#getDefaultImageMetadata61* @see javax.imageio.ImageWriter#write62* @see javax.imageio.ImageWriter#convertImageMetadata63* @see javax.imageio.ImageWriter#convertStreamMetadata64* @see javax.imageio.IIOImage65* @see javax.imageio.ImageTranscoder66*67*/68public abstract class IIOMetadata {6970/**71* A boolean indicating whether the concrete subclass supports the72* standard metadata format, set via the constructor.73*/74protected boolean standardFormatSupported;7576/**77* The name of the native metadata format for this object,78* initialized to {@code null} and set via the constructor.79*/80protected String nativeMetadataFormatName = null;8182/**83* The name of the class implementing {@code IIOMetadataFormat}84* and representing the native metadata format, initialized to85* {@code null} and set via the constructor.86*/87protected String nativeMetadataFormatClassName = null;8889/**90* An array of names of formats, other than the standard and91* native formats, that are supported by this plug-in,92* initialized to {@code null} and set via the constructor.93*/94protected String[] extraMetadataFormatNames = null;9596/**97* An array of names of classes implementing {@code IIOMetadataFormat}98* and representing the metadata formats, other than the standard and99* native formats, that are supported by this plug-in,100* initialized to {@code null} and set via the constructor.101*/102protected String[] extraMetadataFormatClassNames = null;103104/**105* An {@code IIOMetadataController} that is suggested for use106* as the controller for this {@code IIOMetadata} object. It107* may be retrieved via {@code getDefaultController}. To108* install the default controller, call109* {@code setController(getDefaultController())}. This110* instance variable should be set by subclasses that choose to111* provide their own default controller, usually a GUI, for112* setting parameters.113*114* @see IIOMetadataController115* @see #getDefaultController116*/117protected IIOMetadataController defaultController = null;118119/**120* The {@code IIOMetadataController} that will be121* used to provide settings for this {@code IIOMetadata}122* object when the {@code activateController} method123* is called. This value overrides any default controller,124* even when {@code null}.125*126* @see IIOMetadataController127* @see #setController(IIOMetadataController)128* @see #hasController()129* @see #activateController()130*/131protected IIOMetadataController controller = null;132133/**134* Constructs an empty {@code IIOMetadata} object. The135* subclass is responsible for supplying values for all protected136* instance variables that will allow any non-overridden default137* implementations of methods to satisfy their contracts. For example,138* {@code extraMetadataFormatNames} should not have length 0.139*/140protected IIOMetadata() {}141142/**143* Constructs an {@code IIOMetadata} object with the given144* format names and format class names, as well as a boolean145* indicating whether the standard format is supported.146*147* <p> This constructor does not attempt to check the class names148* for validity. Invalid class names may cause exceptions in149* subsequent calls to {@code getMetadataFormat}.150*151* @param standardMetadataFormatSupported {@code true} if152* this object can return or accept a DOM tree using the standard153* metadata format.154* @param nativeMetadataFormatName the name of the native metadata155* format, as a {@code String}, or {@code null} if there156* is no native format.157* @param nativeMetadataFormatClassName the name of the class of158* the native metadata format, or {@code null} if there is159* no native format.160* @param extraMetadataFormatNames an array of {@code String}s161* indicating additional formats supported by this object, or162* {@code null} if there are none.163* @param extraMetadataFormatClassNames an array of {@code String}s164* indicating the class names of any additional formats supported by165* this object, or {@code null} if there are none.166*167* @exception IllegalArgumentException if168* {@code extraMetadataFormatNames} has length 0.169* @exception IllegalArgumentException if170* {@code extraMetadataFormatNames} and171* {@code extraMetadataFormatClassNames} are neither both172* {@code null}, nor of the same length.173*/174protected IIOMetadata(boolean standardMetadataFormatSupported,175String nativeMetadataFormatName,176String nativeMetadataFormatClassName,177String[] extraMetadataFormatNames,178String[] extraMetadataFormatClassNames) {179this.standardFormatSupported = standardMetadataFormatSupported;180this.nativeMetadataFormatName = nativeMetadataFormatName;181this.nativeMetadataFormatClassName = nativeMetadataFormatClassName;182if (extraMetadataFormatNames != null) {183if (extraMetadataFormatNames.length == 0) {184throw new IllegalArgumentException185("extraMetadataFormatNames.length == 0!");186}187if (extraMetadataFormatClassNames == null) {188throw new IllegalArgumentException189("extraMetadataFormatNames != null && extraMetadataFormatClassNames == null!");190}191if (extraMetadataFormatClassNames.length !=192extraMetadataFormatNames.length) {193throw new IllegalArgumentException194("extraMetadataFormatClassNames.length != extraMetadataFormatNames.length!");195}196this.extraMetadataFormatNames = extraMetadataFormatNames.clone();197this.extraMetadataFormatClassNames = extraMetadataFormatClassNames.clone();198} else {199if (extraMetadataFormatClassNames != null) {200throw new IllegalArgumentException201("extraMetadataFormatNames == null && extraMetadataFormatClassNames != null!");202}203}204}205206/**207* Returns {@code true} if the standard metadata format is208* supported by {@code getMetadataFormat},209* {@code getAsTree}, {@code setFromTree}, and210* {@code mergeTree}.211*212* <p> The default implementation returns the value of the213* {@code standardFormatSupported} instance variable.214*215* @return {@code true} if the standard metadata format216* is supported.217*218* @see #getAsTree219* @see #setFromTree220* @see #mergeTree221* @see #getMetadataFormat222*/223public boolean isStandardMetadataFormatSupported() {224return standardFormatSupported;225}226227/**228* Returns {@code true} if this object does not support the229* {@code mergeTree}, {@code setFromTree}, and230* {@code reset} methods.231*232* @return true if this {@code IIOMetadata} object cannot be233* modified.234*/235public abstract boolean isReadOnly();236237/**238* Returns the name of the "native" metadata format for this239* plug-in, which typically allows for lossless encoding and240* transmission of the metadata stored in the format handled by241* this plug-in. If no such format is supported,242* {@code null} will be returned.243*244* <p> The structure and contents of the "native" metadata format245* are defined by the plug-in that created this246* {@code IIOMetadata} object. Plug-ins for simple formats247* will usually create a dummy node for the root, and then a248* series of child nodes representing individual tags, chunks, or249* keyword/value pairs. A plug-in may choose whether or not to250* document its native format.251*252* <p> The default implementation returns the value of the253* {@code nativeMetadataFormatName} instance variable.254*255* @return the name of the native format, or {@code null}.256*257* @see #getExtraMetadataFormatNames258* @see #getMetadataFormatNames259*/260public String getNativeMetadataFormatName() {261return nativeMetadataFormatName;262}263264/**265* Returns an array of {@code String}s containing the names266* of additional metadata formats, other than the native and standard267* formats, recognized by this plug-in's268* {@code getAsTree}, {@code setFromTree}, and269* {@code mergeTree} methods. If there are no such additional270* formats, {@code null} is returned.271*272* <p> The default implementation returns a clone of the273* {@code extraMetadataFormatNames} instance variable.274*275* @return an array of {@code String}s with length at least276* 1, or {@code null}.277*278* @see #getAsTree279* @see #setFromTree280* @see #mergeTree281* @see #getNativeMetadataFormatName282* @see #getMetadataFormatNames283*/284public String[] getExtraMetadataFormatNames() {285if (extraMetadataFormatNames == null) {286return null;287}288return extraMetadataFormatNames.clone();289}290291/**292* Returns an array of {@code String}s containing the names293* of all metadata formats, including the native and standard294* formats, recognized by this plug-in's {@code getAsTree},295* {@code setFromTree}, and {@code mergeTree} methods.296* If there are no such formats, {@code null} is returned.297*298* <p> The default implementation calls299* {@code getNativeMetadataFormatName},300* {@code isStandardMetadataFormatSupported}, and301* {@code getExtraMetadataFormatNames} and returns the302* combined results.303*304* @return an array of {@code String}s.305*306* @see #getNativeMetadataFormatName307* @see #isStandardMetadataFormatSupported308* @see #getExtraMetadataFormatNames309*/310public String[] getMetadataFormatNames() {311String nativeName = getNativeMetadataFormatName();312String standardName = isStandardMetadataFormatSupported() ?313IIOMetadataFormatImpl.standardMetadataFormatName : null;314String[] extraNames = getExtraMetadataFormatNames();315316int numFormats = 0;317if (nativeName != null) {318++numFormats;319}320if (standardName != null) {321++numFormats;322}323if (extraNames != null) {324numFormats += extraNames.length;325}326if (numFormats == 0) {327return null;328}329330String[] formats = new String[numFormats];331int index = 0;332if (nativeName != null) {333formats[index++] = nativeName;334}335if (standardName != null) {336formats[index++] = standardName;337}338if (extraNames != null) {339for (int i = 0; i < extraNames.length; i++) {340formats[index++] = extraNames[i];341}342}343344return formats;345}346347/**348* Returns an {@code IIOMetadataFormat} object describing the349* given metadata format, or {@code null} if no description350* is available. The supplied name must be one of those returned351* by {@code getMetadataFormatNames} (<i>i.e.</i>, either the352* native format name, the standard format name, or one of those353* returned by {@code getExtraMetadataFormatNames}).354*355* <p> The default implementation checks the name against the356* global standard metadata format name, and returns that format357* if it is supported. Otherwise, it checks against the native358* format names followed by any additional format names. If a359* match is found, it retrieves the name of the360* {@code IIOMetadataFormat} class from361* {@code nativeMetadataFormatClassName} or362* {@code extraMetadataFormatClassNames} as appropriate, and363* constructs an instance of that class using its364* {@code getInstance} method.365*366* @param formatName the desired metadata format.367*368* @return an {@code IIOMetadataFormat} object.369*370* @exception IllegalArgumentException if {@code formatName}371* is {@code null} or is not one of the names recognized by372* the plug-in.373* @exception IllegalStateException if the class corresponding to374* the format name cannot be loaded.375*/376public IIOMetadataFormat getMetadataFormat(String formatName) {377if (formatName == null) {378throw new IllegalArgumentException("formatName == null!");379}380if (standardFormatSupported381&& formatName.equals382(IIOMetadataFormatImpl.standardMetadataFormatName)) {383return IIOMetadataFormatImpl.getStandardFormatInstance();384}385String formatClassName = null;386if (formatName.equals(nativeMetadataFormatName)) {387formatClassName = nativeMetadataFormatClassName;388} else if (extraMetadataFormatNames != null) {389for (int i = 0; i < extraMetadataFormatNames.length; i++) {390if (formatName.equals(extraMetadataFormatNames[i])) {391formatClassName = extraMetadataFormatClassNames[i];392break; // out of for393}394}395}396if (formatClassName == null) {397throw new IllegalArgumentException("Unsupported format name");398}399try {400final String className = formatClassName;401// Try to load from the module of the IIOMetadata implementation402// for this plugin since the IIOMetadataImpl is part of the plugin403PrivilegedAction<Class<?>> pa = () -> { return getMetadataFormatClass(className); };404@SuppressWarnings("removal")405Class<?> cls = AccessController.doPrivileged(pa);406Method meth = cls.getMethod("getInstance");407return (IIOMetadataFormat) meth.invoke(null);408} catch (Exception e) {409RuntimeException ex =410new IllegalStateException ("Can't obtain format");411ex.initCause(e);412throw ex;413}414}415416// If updating this method also see the same in ImageReaderWriterSpi.java417private Class<?> getMetadataFormatClass(String formatClassName) {418Module thisModule = IIOMetadata.class.getModule();419Module targetModule = this.getClass().getModule();420Class<?> c = null;421try {422ClassLoader cl = this.getClass().getClassLoader();423c = Class.forName(formatClassName, false, cl);424if (!IIOMetadataFormat.class.isAssignableFrom(c)) {425return null;426}427} catch (ClassNotFoundException e) {428}429if (thisModule.equals(targetModule) || c == null) {430return c;431}432if (targetModule.isNamed()) {433int i = formatClassName.lastIndexOf(".");434String pn = i > 0 ? formatClassName.substring(0, i) : "";435if (!targetModule.isExported(pn, thisModule)) {436throw new IllegalStateException("Class " + formatClassName +437" in named module must be exported to java.desktop module.");438}439}440return c;441}442443/**444* Returns an XML DOM {@code Node} object that represents the445* root of a tree of metadata contained within this object446* according to the conventions defined by a given metadata447* format.448*449* <p> The names of the available metadata formats may be queried450* using the {@code getMetadataFormatNames} method.451*452* @param formatName the desired metadata format.453*454* @return an XML DOM {@code Node} object forming the455* root of a tree.456*457* @exception IllegalArgumentException if {@code formatName}458* is {@code null} or is not one of the names returned by459* {@code getMetadataFormatNames}.460*461* @see #getMetadataFormatNames462* @see #setFromTree463* @see #mergeTree464*/465public abstract Node getAsTree(String formatName);466467/**468* Alters the internal state of this {@code IIOMetadata}469* object from a tree of XML DOM {@code Node}s whose syntax470* is defined by the given metadata format. The previous state is471* altered only as necessary to accommodate the nodes that are472* present in the given tree. If the tree structure or contents473* are invalid, an {@code IIOInvalidTreeException} will be474* thrown.475*476* <p> As the semantics of how a tree or subtree may be merged with477* another tree are completely format-specific, plug-in authors may478* implement this method in whatever manner is most appropriate for479* the format, including simply replacing all existing state with the480* contents of the given tree.481*482* @param formatName the desired metadata format.483* @param root an XML DOM {@code Node} object forming the484* root of a tree.485*486* @exception IllegalStateException if this object is read-only.487* @exception IllegalArgumentException if {@code formatName}488* is {@code null} or is not one of the names returned by489* {@code getMetadataFormatNames}.490* @exception IllegalArgumentException if {@code root} is491* {@code null}.492* @exception IIOInvalidTreeException if the tree cannot be parsed493* successfully using the rules of the given format.494*495* @see #getMetadataFormatNames496* @see #getAsTree497* @see #setFromTree498*/499public abstract void mergeTree(String formatName, Node root)500throws IIOInvalidTreeException;501502/**503* Returns an {@code IIOMetadataNode} representing the chroma504* information of the standard {@code javax_imageio_1.0}505* metadata format, or {@code null} if no such information is506* available. This method is intended to be called by the utility507* routine {@code getStandardTree}.508*509* <p> The default implementation returns {@code null}.510*511* <p> Subclasses should override this method to produce an512* appropriate subtree if they wish to support the standard513* metadata format.514*515* @return an {@code IIOMetadataNode}, or {@code null}.516*517* @see #getStandardTree518*/519protected IIOMetadataNode getStandardChromaNode() {520return null;521}522523/**524* Returns an {@code IIOMetadataNode} representing the525* compression information of the standard526* {@code javax_imageio_1.0} metadata format, or527* {@code null} if no such information is available. This528* method is intended to be called by the utility routine529* {@code getStandardTree}.530*531* <p> The default implementation returns {@code null}.532*533* <p> Subclasses should override this method to produce an534* appropriate subtree if they wish to support the standard535* metadata format.536*537* @return an {@code IIOMetadataNode}, or {@code null}.538*539* @see #getStandardTree540*/541protected IIOMetadataNode getStandardCompressionNode() {542return null;543}544545/**546* Returns an {@code IIOMetadataNode} representing the data547* format information of the standard548* {@code javax_imageio_1.0} metadata format, or549* {@code null} if no such information is available. This550* method is intended to be called by the utility routine551* {@code getStandardTree}.552*553* <p> The default implementation returns {@code null}.554*555* <p> Subclasses should override this method to produce an556* appropriate subtree if they wish to support the standard557* metadata format.558*559* @return an {@code IIOMetadataNode}, or {@code null}.560*561* @see #getStandardTree562*/563protected IIOMetadataNode getStandardDataNode() {564return null;565}566567/**568* Returns an {@code IIOMetadataNode} representing the569* dimension information of the standard570* {@code javax_imageio_1.0} metadata format, or571* {@code null} if no such information is available. This572* method is intended to be called by the utility routine573* {@code getStandardTree}.574*575* <p> The default implementation returns {@code null}.576*577* <p> Subclasses should override this method to produce an578* appropriate subtree if they wish to support the standard579* metadata format.580*581* @return an {@code IIOMetadataNode}, or {@code null}.582*583* @see #getStandardTree584*/585protected IIOMetadataNode getStandardDimensionNode() {586return null;587}588589/**590* Returns an {@code IIOMetadataNode} representing the document591* information of the standard {@code javax_imageio_1.0}592* metadata format, or {@code null} if no such information is593* available. This method is intended to be called by the utility594* routine {@code getStandardTree}.595*596* <p> The default implementation returns {@code null}.597*598* <p> Subclasses should override this method to produce an599* appropriate subtree if they wish to support the standard600* metadata format.601*602* @return an {@code IIOMetadataNode}, or {@code null}.603*604* @see #getStandardTree605*/606protected IIOMetadataNode getStandardDocumentNode() {607return null;608}609610/**611* Returns an {@code IIOMetadataNode} representing the textual612* information of the standard {@code javax_imageio_1.0}613* metadata format, or {@code null} if no such information is614* available. This method is intended to be called by the utility615* routine {@code getStandardTree}.616*617* <p> The default implementation returns {@code null}.618*619* <p> Subclasses should override this method to produce an620* appropriate subtree if they wish to support the standard621* metadata format.622*623* @return an {@code IIOMetadataNode}, or {@code null}.624*625* @see #getStandardTree626*/627protected IIOMetadataNode getStandardTextNode() {628return null;629}630631/**632* Returns an {@code IIOMetadataNode} representing the tiling633* information of the standard {@code javax_imageio_1.0}634* metadata format, or {@code null} if no such information is635* available. This method is intended to be called by the utility636* routine {@code getStandardTree}.637*638* <p> The default implementation returns {@code null}.639*640* <p> Subclasses should override this method to produce an641* appropriate subtree if they wish to support the standard642* metadata format.643*644* @return an {@code IIOMetadataNode}, or {@code null}.645*646* @see #getStandardTree647*/648protected IIOMetadataNode getStandardTileNode() {649return null;650}651652/**653* Returns an {@code IIOMetadataNode} representing the654* transparency information of the standard655* {@code javax_imageio_1.0} metadata format, or656* {@code null} if no such information is available. This657* method is intended to be called by the utility routine658* {@code getStandardTree}.659*660* <p> The default implementation returns {@code null}.661*662* <p> Subclasses should override this method to produce an663* appropriate subtree if they wish to support the standard664* metadata format.665*666* @return an {@code IIOMetadataNode}, or {@code null}.667*/668protected IIOMetadataNode getStandardTransparencyNode() {669return null;670}671672/**673* Appends a new node to an existing node, if the new node is674* non-{@code null}.675*/676private void append(IIOMetadataNode root, IIOMetadataNode node) {677if (node != null) {678root.appendChild(node);679}680}681682/**683* A utility method to return a tree of684* {@code IIOMetadataNode}s representing the metadata685* contained within this object according to the conventions of686* the standard {@code javax_imageio_1.0} metadata format.687*688* <p> This method calls the various {@code getStandard*Node}689* methods to supply each of the subtrees rooted at the children690* of the root node. If any of those methods returns691* {@code null}, the corresponding subtree will be omitted.692* If all of them return {@code null}, a tree consisting of a693* single root node will be returned.694*695* @return an {@code IIOMetadataNode} representing the root696* of a metadata tree in the {@code javax_imageio_1.0}697* format.698*699* @see #getStandardChromaNode700* @see #getStandardCompressionNode701* @see #getStandardDataNode702* @see #getStandardDimensionNode703* @see #getStandardDocumentNode704* @see #getStandardTextNode705* @see #getStandardTileNode706* @see #getStandardTransparencyNode707*/708protected final IIOMetadataNode getStandardTree() {709IIOMetadataNode root = new IIOMetadataNode710(IIOMetadataFormatImpl.standardMetadataFormatName);711append(root, getStandardChromaNode());712append(root, getStandardCompressionNode());713append(root, getStandardDataNode());714append(root, getStandardDimensionNode());715append(root, getStandardDocumentNode());716append(root, getStandardTextNode());717append(root, getStandardTileNode());718append(root, getStandardTransparencyNode());719return root;720}721722/**723* Sets the internal state of this {@code IIOMetadata} object724* from a tree of XML DOM {@code Node}s whose syntax is725* defined by the given metadata format. The previous state is726* discarded. If the tree's structure or contents are invalid, an727* {@code IIOInvalidTreeException} will be thrown.728*729* <p> The default implementation calls {@code reset}730* followed by {@code mergeTree(formatName, root)}.731*732* @param formatName the desired metadata format.733* @param root an XML DOM {@code Node} object forming the734* root of a tree.735*736* @exception IllegalStateException if this object is read-only.737* @exception IllegalArgumentException if {@code formatName}738* is {@code null} or is not one of the names returned by739* {@code getMetadataFormatNames}.740* @exception IllegalArgumentException if {@code root} is741* {@code null}.742* @exception IIOInvalidTreeException if the tree cannot be parsed743* successfully using the rules of the given format.744*745* @see #getMetadataFormatNames746* @see #getAsTree747* @see #mergeTree748*/749public void setFromTree(String formatName, Node root)750throws IIOInvalidTreeException {751reset();752mergeTree(formatName, root);753}754755/**756* Resets all the data stored in this object to default values,757* usually to the state this object was in immediately after758* construction, though the precise semantics are plug-in specific.759* Note that there are many possible default values, depending on760* how the object was created.761*762* @exception IllegalStateException if this object is read-only.763*764* @see javax.imageio.ImageReader#getStreamMetadata765* @see javax.imageio.ImageReader#getImageMetadata766* @see javax.imageio.ImageWriter#getDefaultStreamMetadata767* @see javax.imageio.ImageWriter#getDefaultImageMetadata768*/769public abstract void reset();770771/**772* Sets the {@code IIOMetadataController} to be used773* to provide settings for this {@code IIOMetadata}774* object when the {@code activateController} method775* is called, overriding any default controller. If the776* argument is {@code null}, no controller will be777* used, including any default. To restore the default, use778* {@code setController(getDefaultController())}.779*780* <p> The default implementation sets the {@code controller}781* instance variable to the supplied value.782*783* @param controller An appropriate784* {@code IIOMetadataController}, or {@code null}.785*786* @see IIOMetadataController787* @see #getController788* @see #getDefaultController789* @see #hasController790* @see #activateController()791*/792public void setController(IIOMetadataController controller) {793this.controller = controller;794}795796/**797* Returns whatever {@code IIOMetadataController} is currently798* installed. This could be the default if there is one,799* {@code null}, or the argument of the most recent call800* to {@code setController}.801*802* <p> The default implementation returns the value of the803* {@code controller} instance variable.804*805* @return the currently installed806* {@code IIOMetadataController}, or {@code null}.807*808* @see IIOMetadataController809* @see #setController810* @see #getDefaultController811* @see #hasController812* @see #activateController()813*/814public IIOMetadataController getController() {815return controller;816}817818/**819* Returns the default {@code IIOMetadataController}, if there820* is one, regardless of the currently installed controller. If821* there is no default controller, returns {@code null}.822*823* <p> The default implementation returns the value of the824* {@code defaultController} instance variable.825*826* @return the default {@code IIOMetadataController}, or827* {@code null}.828*829* @see IIOMetadataController830* @see #setController(IIOMetadataController)831* @see #getController832* @see #hasController833* @see #activateController()834*/835public IIOMetadataController getDefaultController() {836return defaultController;837}838839/**840* Returns {@code true} if there is a controller installed841* for this {@code IIOMetadata} object.842*843* <p> The default implementation returns {@code true} if the844* {@code getController} method returns a845* non-{@code null} value.846*847* @return {@code true} if a controller is installed.848*849* @see IIOMetadataController850* @see #setController(IIOMetadataController)851* @see #getController852* @see #getDefaultController853* @see #activateController()854*/855public boolean hasController() {856return (getController() != null);857}858859/**860* Activates the installed {@code IIOMetadataController} for861* this {@code IIOMetadata} object and returns the resulting862* value. When this method returns {@code true}, all values for this863* {@code IIOMetadata} object will be ready for the next write864* operation. If {@code false} is865* returned, no settings in this object will have been disturbed866* (<i>i.e.</i>, the user canceled the operation).867*868* <p> Ordinarily, the controller will be a GUI providing a user869* interface for a subclass of {@code IIOMetadata} for a870* particular plug-in. Controllers need not be GUIs, however.871*872* <p> The default implementation calls {@code getController}873* and the calls {@code activate} on the returned object if874* {@code hasController} returns {@code true}.875*876* @return {@code true} if the controller completed normally.877*878* @exception IllegalStateException if there is no controller879* currently installed.880*881* @see IIOMetadataController882* @see #setController(IIOMetadataController)883* @see #getController884* @see #getDefaultController885* @see #hasController886*/887public boolean activateController() {888if (!hasController()) {889throw new IllegalStateException("hasController() == false!");890}891return getController().activate(this);892}893}894895896