36fff55037ed857a3b211f200e7a2b35b31cb8bc
[jSite.git] / src / main / java / de / todesbaum / jsite / application / Project.java
1 /*
2  * jSite - Project.java - Copyright © 2006–2012 David Roden
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation; either version 2 of the License, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16  * Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 package de.todesbaum.jsite.application;
20
21 import java.io.File;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import net.pterodactylus.util.io.MimeTypes;
28
29 /**
30  * Container for project information.
31  *
32  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
33  */
34 public class Project implements Comparable<Project> {
35
36         /** The name of the project. */
37         protected String name;
38
39         /** The description of the project. */
40         protected String description;
41
42         /** The insert URI of the project. */
43         protected String insertURI;
44
45         /** The request URI of the project. */
46         protected String requestURI;
47
48         /** The index file of the project. */
49         protected String indexFile;
50
51         /** The local path of the project. */
52         protected String localPath;
53
54         /** The remote path of the URI. */
55         protected String path;
56
57         /** The time of the last insertion. */
58         protected long lastInsertionTime;
59
60         /** The edition to insert to. */
61         protected int edition;
62
63         /** Whether to ignore hidden directory. */
64         private boolean ignoreHiddenFiles;
65
66         /** Options for files. */
67         protected Map<String, FileOption> fileOptions = new HashMap<String, FileOption>();
68
69         /**
70          * Empty constructor.
71          */
72         public Project() {
73                 /* do nothing. */
74         }
75
76         /**
77          * Creates a new project from an existing one.
78          *
79          * @param project
80          *            The project to clone
81          */
82         public Project(Project project) {
83                 name = project.name;
84                 description = project.description;
85                 insertURI = project.insertURI;
86                 requestURI = project.requestURI;
87                 path = project.path;
88                 edition = project.edition;
89                 localPath = project.localPath;
90                 indexFile = project.indexFile;
91                 lastInsertionTime = project.lastInsertionTime;
92                 ignoreHiddenFiles = project.ignoreHiddenFiles;
93                 fileOptions = new HashMap<String, FileOption>(project.fileOptions);
94         }
95
96         /**
97          * Returns the name of the project.
98          *
99          * @return The name of the project
100          */
101         public String getName() {
102                 return name;
103         }
104
105         /**
106          * Sets the name of the project.
107          *
108          * @param name
109          *            The name of the project
110          */
111         public void setName(String name) {
112                 this.name = name;
113         }
114
115         /**
116          * Returns the description of the project.
117          *
118          * @return The description of the project
119          */
120         public String getDescription() {
121                 return description;
122         }
123
124         /**
125          * Sets the description of the project.
126          *
127          * @param description
128          *            The description of the project
129          */
130         public void setDescription(String description) {
131                 this.description = description;
132         }
133
134         /**
135          * Returns the local path of the project.
136          *
137          * @return The local path of the project
138          */
139         public String getLocalPath() {
140                 return localPath;
141         }
142
143         /**
144          * Sets the local path of the project.
145          *
146          * @param localPath
147          *            The local path of the project
148          */
149         public void setLocalPath(String localPath) {
150                 this.localPath = localPath;
151         }
152
153         /**
154          * Returns the name of the index file of the project, relative to the
155          * project’s local path.
156          *
157          * @return The name of the index file of the project
158          */
159         public String getIndexFile() {
160                 return indexFile;
161         }
162
163         /**
164          * Sets the name of the index file of the project, relative to the project’s
165          * local path.
166          *
167          * @param indexFile
168          *            The name of the index file of the project
169          */
170         public void setIndexFile(String indexFile) {
171                 this.indexFile = indexFile;
172         }
173
174         /**
175          * Returns the time the project was last inserted, in milliseconds since the
176          * epoch.
177          *
178          * @return The time of the last insertion
179          */
180         public long getLastInsertionTime() {
181                 return lastInsertionTime;
182         }
183
184         /**
185          * Sets the time the project was last inserted, in milliseconds since the
186          * last epoch.
187          *
188          * @param lastInserted
189          *            The time of the last insertion
190          */
191         public void setLastInsertionTime(long lastInserted) {
192                 lastInsertionTime = lastInserted;
193         }
194
195         /**
196          * Returns the remote path of the project. The remote path is the path that
197          * directly follows the request URI of the project.
198          *
199          * @return The remote path of the project
200          */
201         public String getPath() {
202                 return path;
203         }
204
205         /**
206          * Sets the remote path of the project. The remote path is the path that
207          * directly follows the request URI of the project.
208          *
209          * @param path
210          *            The remote path of the project
211          */
212         public void setPath(String path) {
213                 this.path = path;
214         }
215
216         /**
217          * Returns the insert URI of the project.
218          *
219          * @return The insert URI of the project
220          */
221         public String getInsertURI() {
222                 return insertURI;
223         }
224
225         /**
226          * Sets the insert URI of the project.
227          *
228          * @param insertURI
229          *            The insert URI of the project
230          */
231         public void setInsertURI(String insertURI) {
232                 this.insertURI = shortenURI(insertURI);
233         }
234
235         /**
236          * Returns the request URI of the project.
237          *
238          * @return The request URI of the project
239          */
240         public String getRequestURI() {
241                 return requestURI;
242         }
243
244         /**
245          * Sets the request URI of the project.
246          *
247          * @param requestURI
248          *            The request URI of the project
249          */
250         public void setRequestURI(String requestURI) {
251                 this.requestURI = shortenURI(requestURI);
252         }
253
254         /**
255          * Returns whether hidden files are ignored, i.e. not inserted.
256          *
257          * @return {@code true} if hidden files are not inserted, {@code false}
258          *         otherwise
259          */
260         public boolean isIgnoreHiddenFiles() {
261                 return ignoreHiddenFiles;
262         }
263
264         /**
265          * Sets whether hidden files are ignored, i.e. not inserted.
266          *
267          * @param ignoreHiddenFiles
268          *            {@code true} if hidden files are not inserted, {@code false}
269          *            otherwise
270          */
271         public void setIgnoreHiddenFiles(boolean ignoreHiddenFiles) {
272                 this.ignoreHiddenFiles = ignoreHiddenFiles;
273         }
274
275         /**
276          * {@inheritDoc}
277          * <p>
278          * This method returns the name of the project.
279          */
280         @Override
281         public String toString() {
282                 return name;
283         }
284
285         /**
286          * Shortens the given URI by removing scheme and key-type prefixes.
287          *
288          * @param uri
289          *            The URI to shorten
290          * @return The shortened URI
291          */
292         private static String shortenURI(String uri) {
293                 String shortUri = uri;
294                 if (shortUri.startsWith("freenet:")) {
295                         shortUri = shortUri.substring("freenet:".length());
296                 }
297                 if (shortUri.startsWith("SSK@")) {
298                         shortUri = shortUri.substring("SSK@".length());
299                 }
300                 if (shortUri.startsWith("USK@")) {
301                         shortUri = shortUri.substring("USK@".length());
302                 }
303                 if (shortUri.endsWith("/")) {
304                         shortUri = shortUri.substring(0, shortUri.length() - 1);
305                 }
306                 return shortUri;
307         }
308
309         /**
310          * Shortens the name of the given file by removing the local path of the
311          * project and leading file separators.
312          *
313          * @param file
314          *            The file whose name should be shortened
315          * @return The shortened name of the file
316          */
317         public String shortenFilename(File file) {
318                 String filename = file.getPath();
319                 if (filename.startsWith(localPath)) {
320                         filename = filename.substring(localPath.length());
321                         if (filename.startsWith(File.separator)) {
322                                 filename = filename.substring(1);
323                         }
324                 }
325                 return filename;
326         }
327
328         /**
329          * Returns the options for the file with the given name. If the file does
330          * not yet have any options, a new set of default options is created and
331          * returned.
332          *
333          * @param filename
334          *            The name of the file, relative to the project root
335          * @return The options for the file
336          */
337         public FileOption getFileOption(String filename) {
338                 FileOption fileOption = fileOptions.get(filename);
339                 if (fileOption == null) {
340                         fileOption = new FileOption(MimeTypes.getMimeType(filename.substring(filename.lastIndexOf('.') + 1)));
341                         fileOptions.put(filename, fileOption);
342                 }
343                 return fileOption;
344         }
345
346         /**
347          * Sets options for a file.
348          *
349          * @param filename
350          *            The filename to set the options for, relative to the project
351          *            root
352          * @param fileOption
353          *            The options to set for the file, or <code>null</code> to
354          *            remove the options for the file
355          */
356         public void setFileOption(String filename, FileOption fileOption) {
357                 if (fileOption != null) {
358                         fileOptions.put(filename, fileOption);
359                 } else {
360                         fileOptions.remove(filename);
361                 }
362         }
363
364         /**
365          * Returns all file options.
366          *
367          * @return All file options
368          */
369         public Map<String, FileOption> getFileOptions() {
370                 return Collections.unmodifiableMap(fileOptions);
371         }
372
373         /**
374          * Sets all file options.
375          *
376          * @param fileOptions
377          *            The file options
378          */
379         public void setFileOptions(Map<String, FileOption> fileOptions) {
380                 this.fileOptions.clear();
381                 this.fileOptions.putAll(fileOptions);
382         }
383
384         /**
385          * {@inheritDoc}
386          * <p>
387          * Projects are compared by their name only.
388          */
389         @Override
390         public int compareTo(Project project) {
391                 return name.compareToIgnoreCase(project.name);
392         }
393
394         /**
395          * Returns the edition of the project.
396          *
397          * @return The edition of the project
398          */
399         public int getEdition() {
400                 return edition;
401         }
402
403         /**
404          * Sets the edition of the project.
405          *
406          * @param edition
407          *            The edition to set
408          */
409         public void setEdition(int edition) {
410                 this.edition = edition;
411         }
412
413         /**
414          * Constructs the final request URI including the edition number.
415          *
416          * @param offset
417          *            The offset for the edition number
418          * @return The final request URI
419          */
420         public String getFinalRequestURI(int offset) {
421                 return "USK@" + requestURI + "/" + path + "/" + (edition + offset) + "/";
422         }
423
424         /**
425          * Performs some post-processing on the project after it was inserted
426          * successfully. At the moment it copies the current hashes of all file
427          * options to the last insert hashes, updating the hashes for the next
428          * insert.
429          */
430         public void onSuccessfulInsert() {
431                 for (Entry<String, FileOption> fileOptionEntry : fileOptions.entrySet()) {
432                         FileOption fileOption = fileOptionEntry.getValue();
433                         if ((fileOption.getCurrentHash() != null) && (fileOption.getCurrentHash().length() > 0) && (!fileOption.getCurrentHash().equals(fileOption.getLastInsertHash()) || fileOption.isForceInsert())) {
434                                 fileOption.setLastInsertEdition(edition);
435                                 fileOption.setLastInsertHash(fileOption.getCurrentHash());
436                                 fileOption.setLastInsertFilename(fileOption.hasChangedName() ? fileOption.getChangedName() : fileOptionEntry.getKey());
437                         }
438                         fileOption.setForceInsert(false);
439                 }
440         }
441
442 }