1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2;
18
19 import java.util.Arrays;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.util.SortedMap;
23 import java.util.TreeMap;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public final class FileSystemOptions implements Cloneable, Comparable<FileSystemOptions> {
46
47
48
49
50 private static final class FileSystemOptionKey implements Comparable<FileSystemOptionKey> {
51
52 private static final int HASH = 29;
53
54
55 private final Class<? extends FileSystem> fileSystemClass;
56
57
58 private final String name;
59
60
61
62 private FileSystemOptionKey(final Class<? extends FileSystem> fileSystemClass, final String name) {
63 this.fileSystemClass = fileSystemClass;
64 this.name = name;
65 }
66
67 @Override
68 public int compareTo(final FileSystemOptionKey o) {
69 final int ret = fileSystemClass.getName().compareTo(o.fileSystemClass.getName());
70 if (ret != 0) {
71 return ret;
72 }
73 return name.compareTo(o.name);
74 }
75
76 @Override
77 public boolean equals(final Object o) {
78 if (this == o) {
79 return true;
80 }
81 if (o == null || getClass() != o.getClass()) {
82 return false;
83 }
84
85 final FileSystemOptionKey that = (FileSystemOptionKey) o;
86
87 if (!fileSystemClass.equals(that.fileSystemClass)) {
88 return false;
89 }
90 return name.equals(that.name);
91 }
92
93 @Override
94 public int hashCode() {
95 int result;
96 result = fileSystemClass.hashCode();
97 return HASH * result + name.hashCode();
98 }
99
100 @Override
101 public String toString() {
102 return fileSystemClass.getName() + "." + name;
103 }
104 }
105
106
107 private final Map<FileSystemOptionKey, Object> options;
108
109
110
111
112 public FileSystemOptions() {
113 this(new TreeMap<>());
114 }
115
116
117
118
119
120
121
122 public FileSystemOptions(final Map<FileSystemOptionKey, Object> options) {
123 this.options = options;
124 }
125
126
127
128
129
130
131 @Override
132 public Object clone() {
133 return new FileSystemOptions(new TreeMap<>(options));
134 }
135
136 @Override
137 public int compareTo(final FileSystemOptions other) {
138 if (this == other) {
139
140 return 0;
141 }
142
143 final int propsSz = options == null ? 0 : options.size();
144 final int propsFkSz = other.options == null ? 0 : other.options.size();
145 if (propsSz < propsFkSz) {
146 return -1;
147 }
148 if (propsSz > propsFkSz) {
149 return 1;
150 }
151 if (propsSz == 0) {
152
153 return 0;
154 }
155
156
157 final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
158 ? (SortedMap<FileSystemOptionKey, Object>) options
159 : new TreeMap<>(options);
160 final SortedMap<FileSystemOptionKey, Object> theirOptions = other.options instanceof SortedMap
161 ? (SortedMap<FileSystemOptionKey, Object>) other.options
162 : new TreeMap<>(other.options);
163 final Iterator<FileSystemOptionKey> optKeysIter = myOptions.keySet().iterator();
164 final Iterator<FileSystemOptionKey> otherKeysIter = theirOptions.keySet().iterator();
165 while (optKeysIter.hasNext()) {
166 final int comp = optKeysIter.next().compareTo(otherKeysIter.next());
167 if (comp != 0) {
168 return comp;
169 }
170 }
171
172 final int hash = Arrays.deepHashCode(myOptions.values().toArray());
173 final int hashFk = Arrays.deepHashCode(theirOptions.values().toArray());
174 return Integer.compare(hash, hashFk);
175
176
177 }
178
179 @Override
180 public boolean equals(final Object obj) {
181 if (this == obj) {
182 return true;
183 }
184 if (obj == null) {
185 return false;
186 }
187 if (getClass() != obj.getClass()) {
188 return false;
189 }
190 final FileSystemOptions other = (FileSystemOptions) obj;
191 return compareTo(other) == 0;
192 }
193
194 <T> T getOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
195 return getOptionOrDefault(fileSystemClass, name, null);
196 }
197
198 <T> T getOptionOrDefault(final Class<? extends FileSystem> fileSystemClass, final String name, final T defaultValue) {
199 final T value = (T) options.getOrDefault(new FileSystemOptionKey(fileSystemClass, name), defaultValue);
200 return value != null ? value : defaultValue;
201 }
202
203 @Override
204 public int hashCode() {
205 final int prime = 31;
206 int result = 1;
207 if (options == null) {
208 result = prime * result;
209 } else {
210 final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
211 ? (SortedMap<FileSystemOptionKey, Object>) options
212 : new TreeMap<>(options);
213 result = prime * result + myOptions.keySet().hashCode();
214 result = prime * result + Arrays.deepHashCode(myOptions.values().toArray());
215 }
216 return result;
217 }
218
219 boolean hasOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
220 return options.containsKey(new FileSystemOptionKey(fileSystemClass, name));
221 }
222
223 void setOption(final Class<? extends FileSystem> fileSystemClass, final String name, final Object value) {
224 options.put(new FileSystemOptionKey(fileSystemClass, name), value);
225 }
226
227 int size() {
228 return options.size();
229 }
230
231 @Override
232 public String toString() {
233 return options.toString();
234 }
235 }