View Javadoc

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 }