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

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