source: josm/trunk/src/com/drew/metadata/Metadata.java@ 9870

Last change on this file since 9870 was 8243, checked in by Don-vip, 9 years ago

fix #11359 - update to metadata-extractor 2.8.1

File size: 6.9 KB
Line 
1/*
2 * Copyright 2002-2015 Drew Noakes
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * More information about this project is available at:
17 *
18 * https://drewnoakes.com/code/exif/
19 * https://github.com/drewnoakes/metadata-extractor
20 */
21package com.drew.metadata;
22
23import com.drew.lang.annotations.NotNull;
24import com.drew.lang.annotations.Nullable;
25
26import java.util.*;
27
28/**
29 * A top-level object that holds the metadata values extracted from an image.
30 * <p>
31 * Metadata objects may contain zero or more {@link Directory} objects. Each directory may contain zero or more tags
32 * with corresponding values.
33 *
34 * @author Drew Noakes https://drewnoakes.com
35 */
36public final class Metadata
37{
38 @NotNull
39 private final Map<Class<? extends Directory>,Collection<Directory>> _directoryListByClass = new HashMap<Class<? extends Directory>, Collection<Directory>>();
40
41 /**
42 * Returns an iterable set of the {@link Directory} instances contained in this metadata collection.
43 *
44 * @return an iterable set of directories
45 */
46 @NotNull
47 public Iterable<Directory> getDirectories()
48 {
49 return new DirectoryIterable(_directoryListByClass);
50 }
51
52 @Nullable
53 public <T extends Directory> Collection<T> getDirectoriesOfType(Class<T> type)
54 {
55 return (Collection<T>)_directoryListByClass.get(type);
56 }
57
58 /**
59 * Returns the count of directories in this metadata collection.
60 *
61 * @return the number of unique directory types set for this metadata collection
62 */
63 public int getDirectoryCount()
64 {
65 int count = 0;
66 for (Map.Entry<Class<? extends Directory>,Collection<Directory>> pair : _directoryListByClass.entrySet())
67 count += pair.getValue().size();
68 return count;
69 }
70
71 /**
72 * Adds a directory to this metadata collection.
73 *
74 * @param directory the {@link Directory} to add into this metadata collection.
75 */
76 public <T extends Directory> void addDirectory(@NotNull T directory)
77 {
78 getOrCreateDirectoryList(directory.getClass()).add(directory);
79 }
80
81 /**
82 * Gets the first {@link Directory} of the specified type contained within this metadata collection.
83 * If no instances of this type are present, <code>null</code> is returned.
84 *
85 * @param type the Directory type
86 * @param <T> the Directory type
87 * @return the first Directory of type T in this metadata collection, or <code>null</code> if none exist
88 */
89 @Nullable
90 @SuppressWarnings("unchecked")
91 public <T extends Directory> T getFirstDirectoryOfType(@NotNull Class<T> type)
92 {
93 // We suppress the warning here as the code asserts a map signature of Class<T>,T.
94 // So after get(Class<T>) it is for sure the result is from type T.
95
96 Collection<Directory> list = getDirectoryList(type);
97
98 if (list == null || list.isEmpty())
99 return null;
100
101 return (T)list.iterator().next();
102 }
103
104 /**
105 * Indicates whether an instance of the given directory type exists in this Metadata instance.
106 *
107 * @param type the {@link Directory} type
108 * @return <code>true</code> if a {@link Directory} of the specified type exists, otherwise <code>false</code>
109 */
110 public boolean containsDirectoryOfType(Class<? extends Directory> type)
111 {
112 Collection<Directory> list = getDirectoryList(type);
113 return list != null && !list.isEmpty();
114 }
115
116 /**
117 * Indicates whether any errors were reported during the reading of metadata values.
118 * This value will be true if Directory.hasErrors() is true for one of the contained {@link Directory} objects.
119 *
120 * @return whether one of the contained directories has an error
121 */
122 public boolean hasErrors()
123 {
124 for (Directory directory : getDirectories()) {
125 if (directory.hasErrors())
126 return true;
127 }
128 return false;
129 }
130
131 @Override
132 public String toString()
133 {
134 int count = getDirectoryCount();
135 return String.format("Metadata (%d %s)",
136 count,
137 count == 1
138 ? "directory"
139 : "directories");
140 }
141
142 @Nullable
143 private <T extends Directory> Collection<Directory> getDirectoryList(@NotNull Class<T> type)
144 {
145 return _directoryListByClass.get(type);
146 }
147
148 @NotNull
149 private <T extends Directory> Collection<Directory> getOrCreateDirectoryList(@NotNull Class<T> type)
150 {
151 Collection<Directory> collection = getDirectoryList(type);
152 if (collection != null)
153 return collection;
154 collection = new ArrayList<Directory>();
155 _directoryListByClass.put(type, collection);
156 return collection;
157 }
158
159 private static class DirectoryIterable implements Iterable<Directory>
160 {
161 private final Map<Class<? extends Directory>, Collection<Directory>> _map;
162
163 public DirectoryIterable(Map<Class<? extends Directory>, Collection<Directory>> map)
164 {
165 _map = map;
166 }
167
168 public Iterator<Directory> iterator()
169 {
170 return new DirectoryIterator(_map);
171 }
172
173 private static class DirectoryIterator implements Iterator<Directory>
174 {
175 @NotNull
176 private final Iterator<Map.Entry<Class<? extends Directory>, Collection<Directory>>> _mapIterator;
177 @Nullable
178 private Iterator<Directory> _listIterator;
179
180 public DirectoryIterator(Map<Class<? extends Directory>, Collection<Directory>> map)
181 {
182 _mapIterator = map.entrySet().iterator();
183
184 if (_mapIterator.hasNext())
185 _listIterator = _mapIterator.next().getValue().iterator();
186 }
187
188 public boolean hasNext()
189 {
190 return _listIterator != null && (_listIterator.hasNext() || _mapIterator.hasNext());
191 }
192
193 public Directory next()
194 {
195 if (_listIterator == null || (!_listIterator.hasNext() && !_mapIterator.hasNext()))
196 throw new NoSuchElementException();
197
198 while (!_listIterator.hasNext())
199 _listIterator = _mapIterator.next().getValue().iterator();
200
201 return _listIterator.next();
202 }
203
204 public void remove()
205 {
206 throw new UnsupportedOperationException();
207 }
208 }
209 }
210}
Note: See TracBrowser for help on using the repository browser.