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

Last change on this file since 1512 was 1512, checked in by bnemhaus, 4 years ago
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, false);
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.