1 /* 2 * Copyright (c) 2005, 2016, 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 package com.sun.imageio.plugins.tiff; 26 27 import java.util.Arrays; 28 import java.util.List; 29 import javax.imageio.metadata.IIOMetadataNode; 30 import org.w3c.dom.Node; 31 import javax.imageio.plugins.tiff.TIFFDirectory; 32 import javax.imageio.plugins.tiff.TIFFField; 33 import javax.imageio.plugins.tiff.TIFFTag; 34 import javax.imageio.plugins.tiff.TIFFTagSet; 35 36 /** 37 * The {@code Node} representation of a {@code TIFFField} 38 * wherein the child node is procedural rather than buffered. 39 */ 40 public class TIFFFieldNode extends IIOMetadataNode { 41 private static boolean isIFD(TIFFField f) { 42 int type = f.getType(); 43 return f.hasDirectory() && 44 (type == TIFFTag.TIFF_LONG || type == TIFFTag.TIFF_IFD_POINTER); 45 } 46 47 private static String getNodeName(TIFFField f) { 48 return isIFD(f) ? "TIFFIFD" : "TIFFField"; 49 } 50 51 private boolean isIFD; 52 53 private Boolean isInitialized = Boolean.FALSE; 54 55 private TIFFField field; 56 57 public TIFFFieldNode(TIFFField field) { 58 super(getNodeName(field)); 59 60 isIFD = isIFD(field); 61 62 this.field = field; 63 64 TIFFTag tag = field.getTag(); 65 int tagNumber = tag.getNumber(); 66 String tagName = tag.getName(); 67 68 if(isIFD) { 69 if(tagNumber != 0) { 70 setAttribute("parentTagNumber", Integer.toString(tagNumber)); 71 } 72 if(tagName != null) { 73 setAttribute("parentTagName", tagName); 74 } 75 76 TIFFDirectory dir = field.hasDirectory() ? 77 field.getDirectory() : (TIFFDirectory)field.getData(); 78 TIFFTagSet[] tagSets = dir.getTagSets(); 79 if(tagSets != null) { 80 StringBuilder tagSetNames = new StringBuilder(); 81 for(int i = 0; i < tagSets.length; i++) { 82 tagSetNames.append(tagSets[i].getClass().getName()); 83 if(i != tagSets.length - 1) { 84 tagSetNames.append(","); 85 } 86 } 87 setAttribute("tagSets", tagSetNames.toString()); 88 } 89 } else { 90 setAttribute("number", Integer.toString(tagNumber)); 91 setAttribute("name", tagName); 92 } 93 } 94 95 private synchronized void initialize() { 96 if(isInitialized) return; 97 98 if(isIFD) { 99 TIFFDirectory dir = field.hasDirectory() ? 100 field.getDirectory() : (TIFFDirectory)field.getData(); 101 TIFFField[] fields = dir.getTIFFFields(); 102 if(fields != null) { 103 TIFFTagSet[] tagSets = dir.getTagSets(); 104 List<TIFFTagSet> tagSetList = Arrays.asList(tagSets); 105 int numFields = fields.length; 106 for(int i = 0; i < numFields; i++) { 107 TIFFField f = fields[i]; 108 int tagNumber = f.getTagNumber(); 109 TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSetList); 110 111 Node node = f.getAsNativeNode(); 112 113 if (node != null) { 114 appendChild(node); 115 } 116 } 117 } 118 } else { 119 IIOMetadataNode child; 120 int count = field.getCount(); 121 if (field.getType() == TIFFTag.TIFF_UNDEFINED) { 122 child = new IIOMetadataNode("TIFFUndefined"); 123 124 byte[] data = field.getAsBytes(); 125 StringBuffer sb = new StringBuffer(); 126 for (int i = 0; i < count; i++) { 127 sb.append(Integer.toString(data[i] & 0xff)); 128 if (i < count - 1) { 129 sb.append(","); 130 } 131 } 132 child.setAttribute("value", sb.toString()); 133 } else { 134 child = new IIOMetadataNode("TIFF" + 135 TIFFField.getTypeName(field.getType()) + 136 "s"); 137 138 TIFFTag tag = field.getTag(); 139 140 for (int i = 0; i < count; i++) { 141 IIOMetadataNode cchild = 142 new IIOMetadataNode("TIFF" + 143 TIFFField.getTypeName(field.getType())); 144 145 cchild.setAttribute("value", field.getValueAsString(i)); 146 if (tag.hasValueNames() && field.isIntegral()) { 147 int value = field.getAsInt(i); 148 String name = tag.getValueName(value); 149 if (name != null) { 150 cchild.setAttribute("description", name); 151 } 152 } 153 154 child.appendChild(cchild); 155 } 156 } 157 appendChild(child); 158 } 159 160 isInitialized = Boolean.TRUE; 161 } 162 163 // Need to override this method to avoid a stack overflow exception 164 // which will occur if super.appendChild is called from initialize(). 165 public Node appendChild(Node newChild) { 166 if (newChild == null) { 167 throw new NullPointerException("newChild == null!"); 168 } 169 170 return super.insertBefore(newChild, null); 171 } 172 173 // Override all methods which refer to child nodes. 174 175 public boolean hasChildNodes() { 176 initialize(); 177 return super.hasChildNodes(); 178 } 179 180 public int getLength() { 181 initialize(); 182 return super.getLength(); 183 } 184 185 public Node getFirstChild() { 186 initialize(); 187 return super.getFirstChild(); 188 } 189 190 public Node getLastChild() { 191 initialize(); 192 return super.getLastChild(); 193 } 194 195 public Node getPreviousSibling() { 196 initialize(); 197 return super.getPreviousSibling(); 198 } 199 200 public Node getNextSibling() { 201 initialize(); 202 return super.getNextSibling(); 203 } 204 205 public Node insertBefore(Node newChild, 206 Node refChild) { 207 initialize(); 208 return super.insertBefore(newChild, refChild); 209 } 210 211 public Node replaceChild(Node newChild, 212 Node oldChild) { 213 initialize(); 214 return super.replaceChild(newChild, oldChild); 215 } 216 217 public Node removeChild(Node oldChild) { 218 initialize(); 219 return super.removeChild(oldChild); 220 } 221 222 public Node cloneNode(boolean deep) { 223 initialize(); 224 return super.cloneNode(deep); 225 } 226 } --- EOF ---