source: trunk/src/org/expeditee/gui/management/ResourceManager.java@ 1441

Last change on this file since 1441 was 1441, checked in by bnemhaus, 5 years ago

Copying images in Expeditee now duplicates the associated file on the filesystem.
Also changed USER_NAME back to USER.NAME on David's direction.

File size: 10.1 KB
Line 
1package org.expeditee.gui.management;
2
3import java.io.File;
4import java.io.UnsupportedEncodingException;
5import java.net.URL;
6import java.net.URLDecoder;
7import java.nio.file.Path;
8import java.nio.file.Paths;
9import java.util.ArrayList;
10import java.util.List;
11import java.util.function.Predicate;
12
13import org.expeditee.gui.DisplayController;
14import org.expeditee.gui.Frame;
15import org.expeditee.gui.FrameIO;
16import org.expeditee.gui.FrameUtils;
17import org.expeditee.items.Picture;
18import org.expeditee.items.Text;
19import org.expeditee.network.FrameShare;
20import org.expeditee.setting.DirectoryListSetting;
21import org.expeditee.settings.folders.FolderSettings;
22
23public class ResourceManager {
24
25 private static boolean commonInvalidated = false;
26 private static ResourceManager instance = new ResourceManager();
27 protected static ResolvedDirectoryList frames = instance.new ResolvedDirectoryList(FolderSettings.FrameDirs);
28 protected static ResolvedDirectoryList images = instance.new ResolvedDirectoryList(FolderSettings.ImageDirs);
29 protected static ResolvedDirectoryList audio = instance.new ResolvedDirectoryList(FolderSettings.AudioDirs);
30
31 /**
32 * Creates a Frame object from an associated resour
33 * @param frameName
34 * @param knownPath
35 * @param ignoreAnnotationsOnParse
36 * @return
37 */
38 public static Frame getExpediteeFrame(String frameName, String knownPath, boolean ignoreAnnotationsOnParse) {
39 Frame loaded = null;
40 if (knownPath != null) {
41 return FrameIO.LoadKnownPath(knownPath, frameName);
42 } else {
43 List<String> canditateDirectoriesForResource = frames.getDirectories();
44 for (String path: canditateDirectoriesForResource) {
45 loaded = FrameIO.LoadKnownPath(path, frameName);
46 if (loaded != null) {
47 break;
48 }
49 }
50 }
51
52 if (loaded == null && FrameShare.getInstance() != null) {
53 loaded = FrameShare.getInstance().loadFrame(frameName, knownPath);
54 }
55
56 if (loaded != null) {
57 FrameUtils.Parse(loaded, true, ignoreAnnotationsOnParse);
58 FrameIO.setSavedProperties(loaded);
59 }
60
61 return loaded;
62 }
63
64 /**
65 * Creates a picture object from the information stored in the given Text
66 * object.
67 * @param source
68 * The Text file containing the information for sourcing and displaying the information.
69 * @param tryRemote
70 * True if the FrameShare should be consulted to source the image after local locations
71 * have failed to find the corresponding file.
72 * @return
73 */
74 public static Picture getExpediteePicture(Text source, boolean tryRemote) {
75 // Extract useful content from source text.
76 String content = source.getText().replaceFirst("@i:", "");
77 String path = "";
78 String size = "";
79 String fileName = "";
80 content = content.replaceAll("\n", "");
81 content = content.trim();
82
83 // Image file names must contain a '.' to separate the file name from extension.
84 int fileSuffixCharIndex = content.indexOf('.');
85 if (fileSuffixCharIndex < 0) {
86 return null;
87 }
88 // Separate the path to resource file from additional information.
89 int endOfFileNameIndex = content.indexOf(' ', fileSuffixCharIndex);
90 if (endOfFileNameIndex < 0) {
91 path = content;
92 size = "";
93 } else {
94 path = content.substring(0, endOfFileNameIndex);
95 size = content.substring(endOfFileNameIndex).trim();
96 }
97 fileName = path;
98
99 // Redacted images are generated in memory as noise rather than being
100 // associated with a specific resource on the file system. Therefore,
101 // no more work is required.
102 if (fileName.equals(Picture.REDACTED_IMAGE_NAME)) {
103 return new Picture(source, fileName, path, size);
104 }
105
106 // Having gotten to this point, we now have to find the resource described
107 // by this Expeditee Text Item.
108 List<String> canditateDirectoriesForResource = images.getDirectories(source);
109 canditateDirectoriesForResource.add(FrameIO.PARENT_FOLDER);
110
111 // First try finding the resource in the directories specified by the
112 // users settings frame.
113 File resourceFile = null;
114 for (String dir: canditateDirectoriesForResource) {
115 resourceFile = new File(dir + path);
116 if (resourceFile.exists() && !resourceFile.isDirectory()) {
117 break;
118 }
119 }
120
121 // At this point, if resourceFile is pointing to a file object that
122 // either doesn't exist or is a directory, then we have not been able
123 // to find the correct file.
124 //
125 // If the correct file is out there then two more possibilities:
126 // a. The text Item is specifying an absolute path or,
127 // b. The text Item is specifying a path relative to this java project.
128 // These are of the format "/packageA/packageB/filename". For
129 // example: "/org/expeditee/gui.management/ResourceManager.java"
130 if (resourceFile == null || !resourceFile.exists() || resourceFile.isDirectory()) {
131 // Prepare for case a.
132 resourceFile = new File(path);
133 }
134
135 if (!resourceFile.exists() || resourceFile.isDirectory()) {
136 // We are not looking at an absolute path so check option b.
137 URL resourceFileURL = ResourceManager.class.getResource(path);
138
139 // Decode to remove %20 in Windows folder names
140 if (resourceFileURL != null) {
141 try {
142 path = URLDecoder.decode(resourceFileURL.getFile(), "UTF-8");
143 } catch (UnsupportedEncodingException e) {
144 e.printStackTrace();
145 }
146 }
147 } else {
148 // We are looking at an absolute path, option a.
149 path = resourceFile.getPath();
150 }
151
152 // At this point, the resource has not been found locally. One last
153 // option is that the FrameShare might be able to help us.
154 resourceFile = new File(path);
155 if (!resourceFile.exists() || resourceFile.isDirectory()) {
156 if (tryRemote && FrameShare.getInstance().loadImage(fileName, null)) {
157 // Recursive call, but with try remote as false.
158 // The above call to the FrameShare should have gotten us a local copy.
159 return getExpediteePicture(source, false);
160 } else {
161 return null;
162 }
163 }
164
165 // If we have gotten here, we should have found the correct resourceFile
166 return new Picture(source, fileName, path, size);
167 }
168
169 /**
170 * Gets the audio file named 'localFileName' on the file system. Searches
171 * the locations listed in the users settings frame.
172 * @param localFileName
173 * @param parentFrame
174 * @return
175 */
176 public static File getAudioResource(String localFileName, Frame parentFrame) {
177 List<String> directories = audio.getDirectories(parentFrame);
178 directories.add(FrameIO.PARENT_FOLDER);
179 for (String directory: directories) {
180 Path pathToFile = Paths.get(directory).resolve(localFileName);
181 File file = pathToFile.toFile();
182 if (file.exists() && !file.isDirectory()) {
183 return file;
184 }
185 }
186
187 return null;
188 }
189
190 /**
191 * Gets all the audio files that match the given predicate 'includeFile'.
192 * @param includeFile
193 * @param parentFrame
194 * @return
195 */
196 public static List<File> gatherAudioResources(Predicate<File> includeFile, Frame parentFrame) {
197 List<String> directories = audio.getDirectories(parentFrame);
198 directories.add(FrameIO.PARENT_FOLDER);
199 List<File> results = new ArrayList<File>();
200 for (String directory: directories) {
201 File dir = new File(directory);
202 if (dir.exists()) {
203 File[] canditates = dir.listFiles();
204 for (File f: canditates) {
205 if (!f.isDirectory() && includeFile.test(f)) {
206 results.add(f);
207 }
208 }
209 }
210 }
211 return results;
212 }
213
214 public static void invalidateAllResourceDirectories() {
215 commonInvalidated = true;
216 }
217
218 private static void refreshAll() {
219 Frame currentFrame = DisplayController.getCurrentFrame();
220 String framesetPath = currentFrame == null ? null : currentFrame.getFramesetPath();
221 frames.refresh(framesetPath);
222 images.refresh(framesetPath);
223 audio.refresh(framesetPath);
224 }
225
226 protected class ResolvedDirectoryList {
227 private List<String> directories = null;
228 private String contextFramesetPath = null;
229 private DirectoryListSetting source;
230
231 public ResolvedDirectoryList(DirectoryListSetting source) {
232 this.source = source;
233 }
234
235 public List<String> getDirectories(Text context) {
236 return getDirectories(context.getParentOrCurrentFrame());
237 }
238
239 public List<String> getDirectories(Frame context) {
240 String contextPath = context == null ? null : context.getFramesetPath();
241 return getDirectories(contextPath);
242 }
243
244 public List<String> getDirectories() {
245 return getDirectories("");
246 }
247
248 private List<String> getDirectories(String context) {
249 if (commonInvalidated) {
250 ResourceManager.refreshAll();
251 } else {
252 boolean isInitialSet = contextFramesetPath == null && context != null;
253 boolean settingToNull = context == null && contextFramesetPath != null;
254 boolean requiresRefresh = isInitialSet || settingToNull || !contextFramesetPath.equals(context);
255 if (requiresRefresh) {
256 refresh(context);
257 }
258 }
259
260 return directories;
261 }
262
263 private void refresh(String context) {
264
265 List<String> unresolved = source.getAbsoluteDirs();
266 directories = resolve(unresolved, context);
267 contextFramesetPath = context;
268 }
269
270 private List<String> resolve(List<String> unresolved, String context) {
271 if (context == null) {
272 return resolveWithNullContext(unresolved);
273 }
274
275 List<String> resolved = new ArrayList<String>();
276
277 if (unresolved == null) {
278 return resolved;
279 }
280
281 Path expediteeHome = Paths.get(FrameIO.PARENT_FOLDER).toAbsolutePath();
282 Path p = expediteeHome.relativize(Paths.get(context).toAbsolutePath());
283 for (String s: unresolved) {
284 String local = ResourceUtil.substitute(s, ResourceUtil.CURRENT_FRAMESET_FLAG, p.toString());
285 resolved.add(local);
286 }
287 return resolved;
288 }
289
290 private List<String> resolveWithNullContext(List<String> unresolved) {
291 List<String> resolved = new ArrayList<String>();
292
293 if (unresolved == null) {
294 return resolved;
295 }
296
297 for (String s: unresolved) {
298 String local = ResourceUtil.substitute(s, ResourceUtil.CURRENT_FRAMESET_FLAG, "ERROR.");
299 if (s.equals(local)) {
300 resolved.add(local);
301 }
302 }
303
304 return resolved;
305 }
306 }
307}
Note: See TracBrowser for help on using the repository browser.