1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/*
2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2012 The Android Open Source Project
3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License.
6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at
7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software
11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and
14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License.
15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */
16104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
17104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.gallery3d.exif;
18104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.charset.Charset;
20104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.text.SimpleDateFormat;
21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.Arrays;
22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.Date;
23104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
24104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/**
25104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * This class stores information of an EXIF tag. For more information about
26104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * defined EXIF tags, please read the Jeita EXIF 2.2 standard. Tags should be
27104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * instantiated using {@link ExifInterface#buildTag}.
28104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
29104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * @see ExifInterface
30104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */
31104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapublic class ExifTag {
32104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
33104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
34104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
35104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_UNSIGNED_BYTE = 1;
36104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit
38104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * ASCII code. The final byte is terminated with NULL.
39104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
40104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_ASCII = 2;
41104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
42104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
43104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
44104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_UNSIGNED_SHORT = 3;
45104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
48104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_UNSIGNED_LONG = 4;
49104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The RATIONAL type of EXIF standard. It consists of two LONGs. The first
51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * one is the numerator and the second one expresses the denominator.
52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_UNSIGNED_RATIONAL = 5;
54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any
56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * value depending on the field definition.
57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_UNDEFINED = 7;
59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * (2's complement notation).
62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_LONG = 9;
64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first
66104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * one is the numerator and the second one is the denominator.
67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static final short TYPE_RATIONAL = 10;
69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static Charset US_ASCII = Charset.forName("US-ASCII");
71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final int TYPE_TO_SIZE_MAP[] = new int[11];
72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final int UNSIGNED_SHORT_MAX = 65535;
73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final long UNSIGNED_LONG_MAX = 4294967295L;
74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final long LONG_MAX = Integer.MAX_VALUE;
75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final long LONG_MIN = Integer.MIN_VALUE;
76104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
77104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    static {
78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1;
79104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1;
80104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2;
81104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4;
82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8;
83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1;
84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_LONG] = 4;
85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8;
86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    static final int SIZE_UNDEFINED = 0;
89104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
90104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // Exif TagId
91104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private final short mTagId;
92104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // Exif Tag Type
93104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private final short mDataType;
94104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // If tag has defined count
95104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean mHasDefinedDefaultComponentCount;
96104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // Actual data count in tag (should be number of elements in value array)
97104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private int mComponentCountActual;
98104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // The ifd that this tag should be put in
99104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private int mIfd;
100104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // The value (array of elements of type Tag Type)
101104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private Object mValue;
102104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // Value offset in exif header.
103104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private int mOffset;
104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
108104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Returns true if the given IFD is a valid IFD.
109104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static boolean isValidIfd(int ifdId) {
111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return ifdId == IfdId.TYPE_IFD_0 || ifdId == IfdId.TYPE_IFD_1
112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                || ifdId == IfdId.TYPE_IFD_EXIF || ifdId == IfdId.TYPE_IFD_INTEROPERABILITY
113104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                || ifdId == IfdId.TYPE_IFD_GPS;
114104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
115104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
116104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
117104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Returns true if a given type is a valid tag type.
118104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
119104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static boolean isValidType(short type) {
120104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return type == TYPE_UNSIGNED_BYTE || type == TYPE_ASCII ||
121104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                type == TYPE_UNSIGNED_SHORT || type == TYPE_UNSIGNED_LONG ||
122104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                type == TYPE_UNSIGNED_RATIONAL || type == TYPE_UNDEFINED ||
123104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                type == TYPE_LONG || type == TYPE_RATIONAL;
124104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
125104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
126104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // Use builtTag in ExifInterface instead of constructor.
127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    ExifTag(short tagId, short type, int componentCount, int ifd,
128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            boolean hasDefinedComponentCount) {
129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mTagId = tagId;
130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mDataType = type;
131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = componentCount;
132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mHasDefinedDefaultComponentCount = hasDefinedComponentCount;
133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mIfd = ifd;
134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = null;
135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
137104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
138104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the element size of the given data type in bytes.
139104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
140104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_ASCII
141104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_LONG
142104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_RATIONAL
143104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNDEFINED
144104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_BYTE
145104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_LONG
146104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_RATIONAL
147104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_SHORT
148104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
149104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public static int getElementSize(short type) {
150104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return TYPE_TO_SIZE_MAP[type];
151104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
152104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
153104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
154104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Returns the ID of the IFD this tag belongs to.
155104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
156104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see IfdId#TYPE_IFD_0
157104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see IfdId#TYPE_IFD_1
158104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see IfdId#TYPE_IFD_EXIF
159104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see IfdId#TYPE_IFD_GPS
160104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see IfdId#TYPE_IFD_INTEROPERABILITY
161104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
162104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int getIfd() {
163104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mIfd;
164104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
165104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
166104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void setIfd(int ifdId) {
167104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mIfd = ifdId;
168104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
169104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
170104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
171104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the TID of this tag.
172104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
173104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public short getTagId() {
174104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mTagId;
175104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
176104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
177104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
178104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the data type of this tag
179104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
180104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_ASCII
181104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_LONG
182104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_RATIONAL
183104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNDEFINED
184104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_BYTE
185104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_LONG
186104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_RATIONAL
187104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see #TYPE_UNSIGNED_SHORT
188104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
189104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public short getDataType() {
190104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mDataType;
191104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
192104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
193104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
194104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the total data size in bytes of the value of this tag.
195104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
196104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int getDataSize() {
197104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return getComponentCount() * getElementSize(getDataType());
198104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
199104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
200104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
201104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the component count of this tag.
202104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
203104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
204104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // TODO: fix integer overflows with this
205104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int getComponentCount() {
206104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mComponentCountActual;
207104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
208104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
209104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
210104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets the component count of this tag. Call this function before
211104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * setValue() if the length of value does not match the component count.
212104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
213104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void forceSetComponentCount(int count) {
214104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = count;
215104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
216104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
217104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
218104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Returns true if this ExifTag contains value; otherwise, this tag will
219104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * contain an offset value that is determined when the tag is written.
220104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
221104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean hasValue() {
222104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mValue != null;
223104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
224104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
225104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
226104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets integer values into this tag. This method should be used for tags of
227104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_SHORT}. This method will fail if:
228104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
229104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
230104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
231104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
232104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value.length does NOT match the component count in the definition
233104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * for this tag.</li>
234104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
235104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
236104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(int[] value) {
237104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkBadComponentCount(value.length)) {
238104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
239104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
240104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG &&
241104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                mDataType != TYPE_UNSIGNED_LONG) {
242104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
243104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
244104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType == TYPE_UNSIGNED_SHORT && checkOverflowForUnsignedShort(value)) {
245104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
246104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mDataType == TYPE_UNSIGNED_LONG && checkOverflowForUnsignedLong(value)) {
247104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
248104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
249104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
250104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long[] data = new long[value.length];
251104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (int i = 0; i < value.length; i++) {
252104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            data[i] = value[i];
253104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
254104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = data;
255104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = value.length;
256104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return true;
257104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
258104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
259104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
260104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets integer value into this tag. This method should be used for tags of
261104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_SHORT}, or {@link #TYPE_LONG}. This method
262104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * will fail if:
263104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
264104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
265104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
266104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
267104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component count in the definition of this tag is not 1.</li>
268104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
269104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
270104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(int value) {
271104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return setValue(new int[] {
272104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                value
273104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        });
274104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
275104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
276104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
277104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets long values into this tag. This method should be used for tags of
278104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
279104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
280104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
281104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
282104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value.length does NOT match the component count in the definition
283104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * for this tag.</li>
284104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
285104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
286104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(long[] value) {
287104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkBadComponentCount(value.length) || mDataType != TYPE_UNSIGNED_LONG) {
288104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
289104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
290104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkOverflowForUnsignedLong(value)) {
291104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
292104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
293104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = value;
294104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = value.length;
295104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return true;
296104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
297104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
298104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
299104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets long values into this tag. This method should be used for tags of
300104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
301104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
302104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
303104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
304104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component count in the definition for this tag is not 1.</li>
305104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
306104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
307104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(long value) {
308104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return setValue(new long[] {
309104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                value
310104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        });
311104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
312104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
313104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
314104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets a string value into this tag. This method should be used for tags of
315104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_ASCII}. The string is converted to an ASCII string.
316104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Characters that cannot be converted are replaced with '?'. The length of
317104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * the string must be equal to either (component count -1) or (component
318104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * count). The final byte will be set to the string null terminator '\0',
319104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * overwriting the last character in the string if the value.length is equal
320104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * to the component count. This method will fail if:
321104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
322104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The data type is not {@link #TYPE_ASCII} or {@link #TYPE_UNDEFINED}.</li>
323104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The length of the string is not equal to (component count -1) or
324104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * (component count) in the definition for this tag.</li>
325104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
326104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
327104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(String value) {
328104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType != TYPE_ASCII && mDataType != TYPE_UNDEFINED) {
329104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
330104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
331104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
332104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte[] buf = value.getBytes(US_ASCII);
333104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte[] finalBuf = buf;
334104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (buf.length > 0) {
335104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            finalBuf = (buf[buf.length - 1] == 0 || mDataType == TYPE_UNDEFINED) ? buf : Arrays
336104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                .copyOf(buf, buf.length + 1);
337104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mDataType == TYPE_ASCII && mComponentCountActual == 1) {
338104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            finalBuf = new byte[] { 0 };
339104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
340104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int count = finalBuf.length;
341104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkBadComponentCount(count)) {
342104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
343104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
344104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = count;
345104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = finalBuf;
346104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return true;
347104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
348104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
349104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
350104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets Rational values into this tag. This method should be used for tags
351104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
352104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * method will fail if:
353104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
354104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
355104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * or {@link #TYPE_RATIONAL}.</li>
356104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
357104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value.length does NOT match the component count in the definition
358104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * for this tag.</li>
359104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
360104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
361104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see Rational
362104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
363104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(Rational[] value) {
364104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkBadComponentCount(value.length)) {
365104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
366104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
367104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType != TYPE_UNSIGNED_RATIONAL && mDataType != TYPE_RATIONAL) {
368104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
369104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
370104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType == TYPE_UNSIGNED_RATIONAL && checkOverflowForUnsignedRational(value)) {
371104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
372104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mDataType == TYPE_RATIONAL && checkOverflowForRational(value)) {
373104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
374104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
375104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
376104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = value;
377104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = value.length;
378104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return true;
379104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
380104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
381104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
382104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets a Rational value into this tag. This method should be used for tags
383104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
384104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * method will fail if:
385104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
386104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
387104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * or {@link #TYPE_RATIONAL}.</li>
388104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The value overflows.</li>
389104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component count in the definition for this tag is not 1.</li>
390104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
391104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
392104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @see Rational
393104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
394104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(Rational value) {
395104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return setValue(new Rational[] {
396104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                value
397104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        });
398104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
399104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
400104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
401104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets byte values into this tag. This method should be used for tags of
402104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
403104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * will fail if:
404104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
405104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
406104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNDEFINED} .</li>
407104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The length does NOT match the component count in the definition for
408104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * this tag.</li>
409104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
410104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
411104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(byte[] value, int offset, int length) {
412104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (checkBadComponentCount(length)) {
413104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
414104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
415104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) {
416104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
417104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
418104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mValue = new byte[length];
419104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        System.arraycopy(value, offset, mValue, 0, length);
420104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mComponentCountActual = length;
421104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return true;
422104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
423104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
424104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
425104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Equivalent to setValue(value, 0, value.length).
426104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
427104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(byte[] value) {
428104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return setValue(value, 0, value.length);
429104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
430104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
431104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
432104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets byte value into this tag. This method should be used for tags of
433104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
434104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * will fail if:
435104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
436104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
437104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNDEFINED} .</li>
438104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The component count in the definition for this tag is not 1.</li>
439104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
440104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
441104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(byte value) {
442104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return setValue(new byte[] {
443104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                value
444104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        });
445104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
446104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
447104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
448104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets the value for this tag using an appropriate setValue method for the
449104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * given object. This method will fail if:
450104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <ul>
451104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>The corresponding setValue method for the class of the object passed
452104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * in would fail.</li>
453104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * <li>There is no obvious way to cast the object passed in into an EXIF tag
454104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type.</li>
455104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * </ul>
456104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
457104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setValue(Object obj) {
458104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (obj == null) {
459104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
460104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Short) {
461104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(((Short) obj).shortValue() & 0x0ffff);
462104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof String) {
463104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((String) obj);
464104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof int[]) {
465104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((int[]) obj);
466104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof long[]) {
467104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((long[]) obj);
468104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Rational) {
469104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((Rational) obj);
470104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Rational[]) {
471104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((Rational[]) obj);
472104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof byte[]) {
473104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue((byte[]) obj);
474104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Integer) {
475104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(((Integer) obj).intValue());
476104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Long) {
477104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(((Long) obj).longValue());
478104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Byte) {
479104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(((Byte) obj).byteValue());
480104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Short[]) {
481104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            // Nulls in this array are treated as zeroes.
482104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            Short[] arr = (Short[]) obj;
483104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            int[] fin = new int[arr.length];
484104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            for (int i = 0; i < arr.length; i++) {
485104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                fin[i] = (arr[i] == null) ? 0 : arr[i].shortValue() & 0x0ffff;
486104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
487104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(fin);
488104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Integer[]) {
489104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            // Nulls in this array are treated as zeroes.
490104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            Integer[] arr = (Integer[]) obj;
491104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            int[] fin = new int[arr.length];
492104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            for (int i = 0; i < arr.length; i++) {
493104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                fin[i] = (arr[i] == null) ? 0 : arr[i].intValue();
494104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
495104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(fin);
496104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Long[]) {
497104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            // Nulls in this array are treated as zeroes.
498104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            Long[] arr = (Long[]) obj;
499104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            long[] fin = new long[arr.length];
500104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            for (int i = 0; i < arr.length; i++) {
501104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                fin[i] = (arr[i] == null) ? 0 : arr[i].longValue();
502104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
503104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(fin);
504104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (obj instanceof Byte[]) {
505104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            // Nulls in this array are treated as zeroes.
506104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            Byte[] arr = (Byte[]) obj;
507104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            byte[] fin = new byte[arr.length];
508104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            for (int i = 0; i < arr.length; i++) {
509104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                fin[i] = (arr[i] == null) ? 0 : arr[i].byteValue();
510104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
511104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(fin);
512104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else {
513104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
514104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
515104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
516104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
517104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
518104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets a timestamp to this tag. The method converts the timestamp with the
519104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * format of "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}. This
520104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * method will fail if the data type is not {@link #TYPE_ASCII} or the
521104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * component count of this tag is not 20 or undefined.
522104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
523104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param time the number of milliseconds since Jan. 1, 1970 GMT
524104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return true on success
525104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
526104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean setTimeValue(long time) {
527104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe
528104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        synchronized (TIME_FORMAT) {
529104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return setValue(TIME_FORMAT.format(new Date(time)));
530104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
531104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
532104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
533104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
534104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a String. This method should be used for tags of type
535104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_ASCII}.
536104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
537104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the value as a String, or null if the tag's value does not exist
538104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         or cannot be converted to a String.
539104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
540104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String getValueAsString() {
541104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue == null) {
542104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return null;
543104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof String) {
544104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return (String) mValue;
545104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof byte[]) {
546104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return new String((byte[]) mValue, US_ASCII);
547104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
548104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return null;
549104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
550104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
551104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
552104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a String. This method should be used for tags of type
553104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_ASCII}.
554104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
555104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the String to return if the tag's value does not
556104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            exist or cannot be converted to a String.
557104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a String, or the defaultValue.
558104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
559104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String getValueAsString(String defaultValue) {
560104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        String s = getValueAsString();
561104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (s == null) {
562104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return defaultValue;
563104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
564104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return s;
565104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
566104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
567104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
568104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a byte array. This method should be used for tags of
569104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
570104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
571104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the value as a byte array, or null if the tag's value does not
572104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         exist or cannot be converted to a byte array.
573104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
574104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public byte[] getValueAsBytes() {
575104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue instanceof byte[]) {
576104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return (byte[]) mValue;
577104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
578104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return null;
579104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
580104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
581104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
582104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a byte. If there are more than 1 bytes in this value,
583104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * gets the first byte. This method should be used for tags of type
584104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
585104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
586104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the byte to return if tag's value does not exist or
587104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            cannot be converted to a byte.
588104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a byte, or the defaultValue.
589104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
590104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public byte getValueAsByte(byte defaultValue) {
591104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte[] b = getValueAsBytes();
592104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (b == null || b.length < 1) {
593104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return defaultValue;
594104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
595104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return b[0];
596104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
597104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
598104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
599104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as an array of Rationals. This method should be used for
600104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * tags of type {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
601104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
602104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the value as as an array of Rationals, or null if the tag's value
603104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         does not exist or cannot be converted to an array of Rationals.
604104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
605104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public Rational[] getValueAsRationals() {
606104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue instanceof Rational[]) {
607104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return (Rational[]) mValue;
608104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
609104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return null;
610104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
611104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
612104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
613104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a Rational. If there are more than 1 Rationals in this
614104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * value, gets the first one. This method should be used for tags of type
615104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
616104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
617104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the Rational to return if tag's value does not exist
618104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            or cannot be converted to a Rational.
619104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a Rational, or the defaultValue.
620104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
621104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public Rational getValueAsRational(Rational defaultValue) {
622104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        Rational[] r = getValueAsRationals();
623104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (r == null || r.length < 1) {
624104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return defaultValue;
625104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
626104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return r[0];
627104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
628104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
629104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
630104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as a Rational. If there are more than 1 Rationals in this
631104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * value, gets the first one. This method should be used for tags of type
632104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
633104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
634104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the numerator of the Rational to return if tag's
635104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            value does not exist or cannot be converted to a Rational (the
636104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            denominator will be 1).
637104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a Rational, or the defaultValue.
638104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
639104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public Rational getValueAsRational(long defaultValue) {
640104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        Rational defaultVal = new Rational(defaultValue, 1);
641104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return getValueAsRational(defaultVal);
642104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
643104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
644104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
645104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as an array of ints. This method should be used for tags
646104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * of type {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
647104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
648104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the value as as an array of ints, or null if the tag's value does
649104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         not exist or cannot be converted to an array of ints.
650104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
651104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int[] getValueAsInts() {
652104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue == null) {
653104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return null;
654104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof long[]) {
655104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            long[] val = (long[]) mValue;
656104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            int[] arr = new int[val.length];
657104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            for (int i = 0; i < val.length; i++) {
658104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                arr[i] = (int) val[i]; // Truncates
659104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
660104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return arr;
661104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
662104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return null;
663104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
664104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
665104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
666104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as an int. If there are more than 1 ints in this value,
667104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * gets the first one. This method should be used for tags of type
668104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
669104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
670104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the int to return if tag's value does not exist or
671104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            cannot be converted to an int.
672104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a int, or the defaultValue.
673104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
674104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int getValueAsInt(int defaultValue) {
675104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int[] i = getValueAsInts();
676104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (i == null || i.length < 1) {
677104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return defaultValue;
678104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
679104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return i[0];
680104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
681104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
682104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
683104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value as an array of longs. This method should be used for tags
684104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * of type {@link #TYPE_UNSIGNED_LONG}.
685104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
686104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the value as as an array of longs, or null if the tag's value
687104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         does not exist or cannot be converted to an array of longs.
688104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
689104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long[] getValueAsLongs() {
690104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue instanceof long[]) {
691104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return (long[]) mValue;
692104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
693104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return null;
694104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
695104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
696104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
697104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value or null if none exists. If there are more than 1 longs in
698104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * this value, gets the first one. This method should be used for tags of
699104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * type {@link #TYPE_UNSIGNED_LONG}.
700104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
701104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue the long to return if tag's value does not exist or
702104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            cannot be converted to a long.
703104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a long, or the defaultValue.
704104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
705104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long getValueAsLong(long defaultValue) {
706104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long[] l = getValueAsLongs();
707104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (l == null || l.length < 1) {
708104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return defaultValue;
709104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
710104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return l[0];
711104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
712104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
713104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
714104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the tag's value or null if none exists.
715104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
716104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public Object getValue() {
717104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mValue;
718104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
719104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
720104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
721104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets a long representation of the value.
722104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
723104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param defaultValue value to return if there is no value or value is a
724104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            rational with a denominator of 0.
725104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @return the tag's value as a long, or defaultValue if no representation
726104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *         exists.
727104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
728104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long forceGetValueAsLong(long defaultValue) {
729104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long[] l = getValueAsLongs();
730104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (l != null && l.length >= 1) {
731104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return l[0];
732104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
733104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte[] b = getValueAsBytes();
734104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (b != null && b.length >= 1) {
735104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return b[0];
736104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
737104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        Rational[] r = getValueAsRationals();
738104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (r != null && r.length >= 1 && r[0].getDenominator() != 0) {
739104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return (long) r[0].toDouble();
740104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
741104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return defaultValue;
742104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
743104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
744104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
745104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets a string representation of the value.
746104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
747104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String forceGetValueAsString() {
748104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue == null) {
749104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return "";
750104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof byte[]) {
751104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (mDataType == TYPE_ASCII) {
752104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return new String((byte[]) mValue, US_ASCII);
753104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            } else {
754104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return Arrays.toString((byte[]) mValue);
755104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
756104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof long[]) {
757104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (((long[]) mValue).length == 1) {
758104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return String.valueOf(((long[]) mValue)[0]);
759104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            } else {
760104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return Arrays.toString((long[]) mValue);
761104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
762104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof Object[]) {
763104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (((Object[]) mValue).length == 1) {
764104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                Object val = ((Object[]) mValue)[0];
765104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (val == null) {
766104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return "";
767104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else {
768104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return val.toString();
769104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
770104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            } else {
771104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return Arrays.toString((Object[]) mValue);
772104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
773104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else {
774104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return mValue.toString();
775104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
776104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
777104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
778104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
779104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the value for type {@link #TYPE_ASCII}, {@link #TYPE_LONG},
780104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNDEFINED}, {@link #TYPE_UNSIGNED_BYTE},
781104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_UNSIGNED_SHORT}. For
782104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}, call
783104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * {@link #getRational(int)} instead.
784104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
785104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @exception IllegalArgumentException if the data type is
786104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
787104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
788104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected long getValueAt(int index) {
789104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mValue instanceof long[]) {
790104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return ((long[]) mValue)[index];
791104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        } else if (mValue instanceof byte[]) {
792104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return ((byte[]) mValue)[index];
793104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
794104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        throw new IllegalArgumentException("Cannot get integer value from "
795104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                + convertTypeToString(mDataType));
796104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
797104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
798104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
799104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the {@link #TYPE_ASCII} data.
800104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
801104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @exception IllegalArgumentException If the type is NOT
802104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *                {@link #TYPE_ASCII}.
803104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
804104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected String getString() {
805104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mDataType != TYPE_ASCII) {
806104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            throw new IllegalArgumentException("Cannot get ASCII value from "
807104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    + convertTypeToString(mDataType));
808104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
809104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return new String((byte[]) mValue, US_ASCII);
810104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
811104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
812104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /*
813104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Get the converted ascii byte. Used by ExifOutputStream.
814104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
815104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected byte[] getStringByte() {
816104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return (byte[]) mValue;
817104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
818104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
819104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
820104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data.
821104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
822104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @exception IllegalArgumentException If the type is NOT
823104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
824104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
825104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected Rational getRational(int index) {
826104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) {
827104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            throw new IllegalArgumentException("Cannot get RATIONAL value from "
828104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    + convertTypeToString(mDataType));
829104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
830104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return ((Rational[]) mValue)[index];
831104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
832104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
833104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
834104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Equivalent to getBytes(buffer, 0, buffer.length).
835104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
836104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void getBytes(byte[] buf) {
837104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        getBytes(buf, 0, buf.length);
838104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
839104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
840104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
841104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
842104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *
843104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param buf the byte array in which to store the bytes read.
844104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param offset the initial position in buffer to store the bytes.
845104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @param length the maximum number of bytes to store in buffer. If length >
846104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *            component count, only the valid bytes will be stored.
847104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * @exception IllegalArgumentException If the type is NOT
848104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     *                {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
849104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
850104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void getBytes(byte[] buf, int offset, int length) {
851104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) {
852104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            throw new IllegalArgumentException("Cannot get BYTE value from "
853104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    + convertTypeToString(mDataType));
854104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
855104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        System.arraycopy(mValue, 0, buf, offset,
856104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                (length > mComponentCountActual) ? mComponentCountActual : length);
857104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
858104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
859104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
860104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Gets the offset of this tag. This is only valid if this data size > 4 and
861104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * contains an offset to the location of the actual value.
862104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
863104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected int getOffset() {
864104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mOffset;
865104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
866104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
867104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    /**
868104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     * Sets the offset of this tag.
869104c45677660586026a7e74ef8c47d396403d50eMichael Jurka     */
870104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void setOffset(int offset) {
871104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mOffset = offset;
872104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
873104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
874104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected void setHasDefinedCount(boolean d) {
875104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mHasDefinedDefaultComponentCount = d;
876104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
877104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
878104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected boolean hasDefinedCount() {
879104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mHasDefinedDefaultComponentCount;
880104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
881104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
882104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkBadComponentCount(int count) {
883104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (mHasDefinedDefaultComponentCount && (mComponentCountActual != count)) {
884104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return true;
885104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
886104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
887104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
888104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
889104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private static String convertTypeToString(short type) {
890104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        switch (type) {
891104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_UNSIGNED_BYTE:
892104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "UNSIGNED_BYTE";
893104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_ASCII:
894104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "ASCII";
895104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_UNSIGNED_SHORT:
896104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "UNSIGNED_SHORT";
897104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_UNSIGNED_LONG:
898104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "UNSIGNED_LONG";
899104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_UNSIGNED_RATIONAL:
900104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "UNSIGNED_RATIONAL";
901104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_UNDEFINED:
902104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "UNDEFINED";
903104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_LONG:
904104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "LONG";
905104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            case TYPE_RATIONAL:
906104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "RATIONAL";
907104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            default:
908104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return "";
909104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
910104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
911104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
912104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkOverflowForUnsignedShort(int[] value) {
913104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (int v : value) {
914104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (v > UNSIGNED_SHORT_MAX || v < 0) {
915104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return true;
916104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
917104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
918104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
919104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
920104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
921104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkOverflowForUnsignedLong(long[] value) {
922104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (long v : value) {
923104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (v < 0 || v > UNSIGNED_LONG_MAX) {
924104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return true;
925104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
926104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
927104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
928104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
929104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
930104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkOverflowForUnsignedLong(int[] value) {
931104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (int v : value) {
932104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (v < 0) {
933104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return true;
934104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
935104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
936104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
937104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
938104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
939104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkOverflowForUnsignedRational(Rational[] value) {
940104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (Rational v : value) {
941104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (v.getNumerator() < 0 || v.getDenominator() < 0
942104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || v.getNumerator() > UNSIGNED_LONG_MAX
943104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || v.getDenominator() > UNSIGNED_LONG_MAX) {
944104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return true;
945104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
946104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
947104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
948104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
949104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
950104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private boolean checkOverflowForRational(Rational[] value) {
951104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        for (Rational v : value) {
952104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (v.getNumerator() < LONG_MIN || v.getDenominator() < LONG_MIN
953104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || v.getNumerator() > LONG_MAX
954104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || v.getDenominator() > LONG_MAX) {
955104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return true;
956104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
957104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
958104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
959104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
960104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
961104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
962104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public boolean equals(Object obj) {
963104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (obj == null) {
964104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            return false;
965104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
966104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (obj instanceof ExifTag) {
967104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            ExifTag tag = (ExifTag) obj;
968104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (tag.mTagId != this.mTagId
969104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || tag.mComponentCountActual != this.mComponentCountActual
970104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    || tag.mDataType != this.mDataType) {
971104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return false;
972104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
973104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            if (mValue != null) {
974104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                if (tag.mValue == null) {
975104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return false;
976104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else if (mValue instanceof long[]) {
977104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (!(tag.mValue instanceof long[])) {
978104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        return false;
979104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
980104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
981104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else if (mValue instanceof Rational[]) {
982104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (!(tag.mValue instanceof Rational[])) {
983104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        return false;
984104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
985104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
986104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else if (mValue instanceof byte[]) {
987104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    if (!(tag.mValue instanceof byte[])) {
988104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                        return false;
989104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    }
990104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
991104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                } else {
992104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                    return mValue.equals(tag.mValue);
993104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                }
994104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            } else {
995104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                return tag.mValue == null;
996104c45677660586026a7e74ef8c47d396403d50eMichael Jurka            }
997104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        }
998104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return false;
999104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
1000104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
1001104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
1002104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String toString() {
1003104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return String.format("tag id: %04X\n", mTagId) + "ifd id: " + mIfd + "\ntype: "
1004104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                + convertTypeToString(mDataType) + "\ncount: " + mComponentCountActual
1005104c45677660586026a7e74ef8c47d396403d50eMichael Jurka                + "\noffset: " + mOffset + "\nvalue: " + forceGetValueAsString() + "\n";
1006104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
1007104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
1008104c45677660586026a7e74ef8c47d396403d50eMichael Jurka}
1009