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

Last change on this file since 1490 was 1490, checked in by bnemhaus, 4 years ago

FrameDirectory Settings can now have paths included in them that are not valid directories.
The check for valid directories now happens in the ResourceManager when the load request is made.

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