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

Last change on this file since 1434 was 1434, checked in by bln4, 5 years ago

Implementation of ProfileManager. Refactor + additional content for how new profiles are created. The refactoring split out the creation of the default profile from user profiles. Refactoring revealed a long term bug that was causing user profiles to generate with incorrect information. The additional content fixed this bug by introducing the ${USER.NAME} variable, so that the default profile frameset can specify resource locations located in the users resource directory.

org.expeditee.auth.AuthenticatorBrowser
org.expeditee.auth.account.Create
org.expeditee.gui.Browser
org.expeditee.gui.management.ProfileManager
org.expeditee.setting.DirectoryListSetting
org.expeditee.setting.ListSetting
org.expeditee.settings.UserSettings

Implementation of ResourceManager as a core location to get resources from the file system. Also the additional variable ${CURRENT_FRAMESET} to represent the current frameset, so that images can be stored in the directory of the current frameset. This increases portability of framesets.

org.expeditee.gui.FrameIO
org.expeditee.gui.management.ResourceManager
org.expeditee.gui.management.ResourceUtil
Audio:

#NB: Audio used to only operate on a single directory. This has been updated to work in a same way as images. That is: when you ask for a specific resouce, it looks to the user settings to find a sequence of directories to look at in order until it manages to find the desired resource.


There is still need however for a single(ish) source of truth for the .banks and .mastermix file. Therefore these files are now always located in resource-<username>\audio.
org.apollo.agents.MelodySearch
org.apollo.audio.structure.AudioStructureModel
org.apollo.audio.util.MultiTrackPlaybackController
org.apollo.audio.util.SoundDesk
org.apollo.gui.FrameLayoutDaemon
org.apollo.io.AudioPathManager
org.apollo.util.AudioPurger
org.apollo.widgets.FramePlayer
org.apollo.widgets.SampledTrack

Images:

org.expeditee.items.ItemUtils

Frames:

org.expeditee.gui.FrameIO

Fixed a error in the FramePlayer class caused by an incorrect use of toArray().

org.apollo.widgets.FramePlayer


Added several short cut keys to allow for the Play/Pause (Ctrl + P), mute (Ctrl + M) and volume up/down (Ctrl + +/-) when hovering over SampledTrack widgets.

org.apollo.widgets.SampledTrack


Changed the way that Authenticate.login parses the new users profile to be more consistance with other similar places in code.

org.expeditee.auth.account.Authenticate


Encapsulated _body, _surrogateItemsBody and _primaryItemsBody in Frame class. Also changed getBody function to take a boolean flag as to if it should respect the current surrogate mode. If it should then it makes sure that labels have not changed since last time getBody was called.

org.expeditee.gui.Frame

File size: 9.9 KB
Line 
1package org.expeditee.gui.management;
2
3import java.io.File;import java.io.FileFilter;
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.