1 /*
2 * Copyright (c) 2007 Creative Sphere Limited.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *
10 * Creative Sphere - initial API and implementation
11 *
12 */
13 package org.abstracthorizon.aequo.file;
14
15 import java.io.File;
16
17 import org.abstracthorizon.aequo.DefaultCompareEntry;
18
19 /**
20 * File compare entry. It adds level, index and hierarchy to compare entry.
21 *
22 *
23 * @author Daniel Sendula
24 */
25 public class FileCompareEntry extends DefaultCompareEntry<File> {
26
27 /** Parent entry or <code>null</code> */
28 protected FileCompareEntry parentEntry;
29
30 /** Level from the root */
31 protected int level;
32
33 /** Children entries */
34 protected FileCompareEntry[] children;
35
36 /** File sizes */
37 protected long[] sizes;
38
39 /** Index in visible list */
40 protected int index = -1;
41
42 /**
43 * Constructor
44 * @param parentEntry parent entry or <code>null</code> for the root
45 * @param files files
46 */
47 public FileCompareEntry(FileCompareEntry parentEntry, File[] files) {
48 super(files);
49 this.parentEntry = parentEntry;
50 sizes = new long[files.length];
51 calculateLevel();
52 }
53
54 /**
55 * Constructor
56 * @param parentEntry parent entry or <code>null</code> for the root
57 * @param files files
58 * @param level level
59 */
60 public FileCompareEntry(FileCompareEntry parentEntry, File[] files, int level) {
61 super(files);
62 this.parentEntry = parentEntry;
63 sizes = new long[files.length];
64 this.level = level;
65 }
66
67 /**
68 * Returns level
69 * @return level
70 */
71 public int getLevel() {
72 return level;
73 }
74
75 /**
76 * Calculates level
77 */
78 protected void calculateLevel() {
79 int i = 0;
80 FileCompareEntry entry = parentEntry;
81 while (entry != null) {
82 i++;
83 entry = entry.parentEntry;
84 }
85 level = i;
86 }
87
88 /**
89 * Updates entry status passing <code>false</code> for status changed
90 */
91 public void updateEntryStatus() {
92 updateEntryStatus(false);
93 }
94
95 /**
96 * Updates entry status with extra notification if entry has been changed
97 *
98 * @param statusChanged knowledge that entry has been changed is passed in here
99 */
100 public void updateEntryStatus(boolean statusChanged) {
101 byte[] oldStatus = new byte[status.length];
102 for (int i = 0; i < oldStatus.length; i++) {
103 oldStatus[i] = status[i];
104 }
105 if (children != null) {
106 long[] newSizes = new long[data.length];
107 for (int i = 0; i < data.length; i++) {
108 newSizes[i] = 0;
109 }
110 for (FileCompareEntry e : children) {
111 for (int i = 0; i < data.length; i++) {
112 newSizes[i] = newSizes[i] + e.sizes[i];
113 }
114 }
115 for (int i = 0; i < data.length; i++) {
116 if (sizes[i] != newSizes[i]) {
117 sizes[i] = newSizes[i];
118 statusChanged = true;
119 }
120 }
121
122 for (int i = 0; i < status.length; i++) {
123 status[i] = children[0].status[i];
124 }
125
126 if (children.length > 1) {
127 for (int j = 1; j < children.length; j++) {
128 for (int i = 0; i < status.length; i++) {
129 if (status[i] != children[j].status[i]) {
130 byte s = status[i];
131 byte c = children[j].status[i];
132 if (c == DIFFERENT) {
133 status[i] = DIFFERENT;
134 } else if (c == LESS) {
135 if (s == EQUAL) {
136 status[i] = c;
137 } else {
138 status[i] = DIFFERENT;
139 }
140 } else if (c == GREATER) {
141 if ((s == DIFFERENT) || (s == LESS)) {
142 status[i] = DIFFERENT;
143 } else {
144 status[i] = c;
145 }
146 } else if (c == EQUAL) {
147 if (s == DIFFERENT) {
148 status[i] = s;
149 } else if (s == GREATER) {
150 status[i] = s;
151 } else {
152 status[i] = LESS;
153 }
154 }
155 }
156 }
157 }
158 }
159 } else if (!statusChanged) {
160 super.updateEntryStatus();
161 }
162 for (int i = 0; i < data.length; i++) {
163 if (data[i].isFile()) {
164 long size = data[i].length();
165 if (sizes[i] != size) {
166 statusChanged = true;
167 sizes[i] = size;
168 }
169 }
170 }
171 int i = 0;
172 while ((i < data.length) && (oldStatus[i] == status[i])) {
173 i++;
174 }
175 if (i < data.length) {
176 statusChanged = true;
177 }
178
179 if (statusChanged && (parentEntry != null)) {
180 notifyEntryChanged(getIndex());
181 parentEntry.updateEntryStatus();
182 }
183 }
184
185 /**
186 * Notifies model that this entry has changed
187 */
188 public void notifyEntryChanged() {
189 notifyEntryChanged(getIndex());
190 }
191
192 /**
193 * Notifies model that entry with given index has changed
194 *
195 * @param index index
196 */
197 protected void notifyEntryChanged(int index) {
198 if ((parentEntry != null) && (index >= 0)) {
199 parentEntry.notifyEntryChanged(index);
200 }
201 }
202
203 /**
204 * Notifies model that his entry has been processed
205 */
206 protected void notifyEntryBeingProcessed() {
207 notifyEntryBeingProcessed(getIndex());
208 }
209
210 /**
211 * Notifies model that entry with given index has been processed
212 */
213 protected void notifyEntryBeingProcessed(int index) {
214 if ((parentEntry != null) && (index >= 0)) {
215 parentEntry.notifyEntryBeingProcessed(index);
216 }
217 }
218
219 /**
220 * Returns <code>true</code> if directory (not file)
221 * @return <code>true</code> if directory (not file)
222 */
223 public boolean hasChildren() {
224 return children != null;
225 }
226
227 /**
228 * Returns children
229 * @return children
230 */
231 public FileCompareEntry[] getChildren() {
232 return children;
233 }
234
235 /**
236 * Returns this entry's index
237 * @return this entry's index
238 */
239 public int getIndex() {
240 return index;
241 }
242
243 /**
244 * Returns file size of asked column
245 * @param column column
246 * @return file size of asked column
247 */
248 public long getSize(int column) {
249 return sizes[column];
250 }
251
252 /**
253 * Returns sizes as an array
254 * @return sizes as an array
255 */
256 public long[] getSizes() {
257 return sizes;
258 }
259
260 /**
261 * Comparator that checks two files for file modification dates.
262 * @param left left file
263 * @param right right file
264 */
265 @SuppressWarnings("unchecked")
266 public byte compare(File left, File right) {
267 if (left == right) {
268 return EQUAL;
269 }
270 if (left.exists() == right.exists()) {
271 if (left.isDirectory() == right.isDirectory()) {
272 if (left.isDirectory()) {
273 return EQUAL;
274 } else {
275 if (left.lastModified() == right.lastModified()) {
276 if (left.length() == right.length()) {
277 return EQUAL;
278 } else {
279 if (left.length() > right.length()) {
280 return GREATER;
281 } else {
282 return LESS;
283 }
284 }
285 } else {
286 if (left.lastModified() > right.lastModified()) {
287 return GREATER;
288 } else {
289 return LESS;
290 }
291 }
292 }
293 } else {
294 if (left.isDirectory()) {
295 return GREATER;
296 } else {
297 return LESS;
298 }
299 }
300
301 } else {
302 if (left.exists()) {
303 return GREATER;
304 } else {
305 return GREATER;
306 }
307 }
308 }
309 }