source: trunk/src/org/expeditee/gui/FrameIO.java@ 427

Last change on this file since 427 was 427, checked in by ra33, 15 years ago
File size: 43.3 KB
Line 
1package org.expeditee.gui;
2
3import java.io.BufferedOutputStream;
4import java.io.BufferedReader;
5import java.io.BufferedWriter;
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.FileNotFoundException;
9import java.io.FileOutputStream;
10import java.io.FileReader;
11import java.io.FileWriter;
12import java.io.IOException;
13import java.io.OutputStream;
14import java.io.OutputStreamWriter;
15import java.io.Writer;
16import java.sql.Time;
17import java.util.Collection;
18import java.util.HashMap;
19import java.util.LinkedList;
20
21import org.expeditee.actions.Actions;
22import org.expeditee.agents.ExistingFramesetException;
23import org.expeditee.io.Conversion;
24import org.expeditee.io.ExpReader;
25import org.expeditee.io.ExpWriter;
26import org.expeditee.io.FrameReader;
27import org.expeditee.io.FrameWriter;
28import org.expeditee.io.KMSReader;
29import org.expeditee.io.KMSWriter;
30import org.expeditee.items.Item;
31import org.expeditee.items.ItemUtils;
32import org.expeditee.items.Permission;
33import org.expeditee.items.Text;
34import org.expeditee.network.FrameShare;
35import org.expeditee.stats.Formatter;
36import org.expeditee.stats.Logger;
37import org.expeditee.stats.SessionStats;
38
39/**
40 * This class provides static methods for all saving and loading of Frames
41 * to\from disk. This class also handles any caching of previously loaded
42 * Frames.
43 *
44 * @author jdm18
45 *
46 */
47public class FrameIO {
48
49 private static final char FRAME_NAME_LAST_CHAR = 'A';
50
51 public static void changeParentFolder(String newFolder) {
52 PARENT_FOLDER = newFolder;
53 PUBLIC_PATH = PARENT_FOLDER + "public" + File.separator;
54 FRAME_PATH = PARENT_FOLDER + "framesets" + File.separator;
55 MESSAGES_PATH = PARENT_FOLDER + "messages" + File.separator;
56 TRASH_PATH = PARENT_FOLDER + "trash" + File.separator;
57 IMAGES_PATH = PARENT_FOLDER + IMAGES_FOLDER;
58 HELP_PATH = PARENT_FOLDER + "documentation" + File.separator;
59 PROFILE_PATH = PARENT_FOLDER + "profiles" + File.separator;
60 EXPORTS_DIR = PARENT_FOLDER + "exports" + File.separator;
61 STATISTICS_DIR = PARENT_FOLDER + "statistics" + File.separator;
62 LOGS_DIR = PARENT_FOLDER + "logs" + File.separator;
63 }
64
65 /**
66 * The default location for storing the framesets. Each frameset has its own
67 * subdirectory in this directory.
68 */
69 public static String IMAGES_FOLDER = "images" + File.separator;
70
71 public static String TRASH_PATH;
72
73 public static String PARENT_FOLDER;
74
75 public static String FRAME_PATH;
76
77 public static String MESSAGES_PATH;
78
79 public static String PUBLIC_PATH;
80
81 public static String IMAGES_PATH;
82
83 public static String HELP_PATH;
84
85 public static String PROFILE_PATH;
86
87 public static String EXPORTS_DIR;
88
89 public static String STATISTICS_DIR;
90
91 public static String LOGS_DIR;
92
93 private static final String INF_FILENAME = "frame.inf";
94
95 public static final String ILLEGAL_CHARS = ";:\\/?";
96
97 public static final int MAX_NAME_LENGTH = 64;
98
99 public static final int MAX_CACHE = 100;
100
101 private static HashMap<String, Frame> _Cache = new FrameCache();
102
103 // private static HashMap<String, String> _FramesetNameCache = new
104 // HashMap<String, String>();
105
106 private static boolean ENABLE_CACHE = true;
107
108 private static boolean _UseCache = true;
109
110 private static boolean _SuspendedCache = false;
111
112 // All methods are static, this should not be instantiated
113 private FrameIO() {
114 }
115
116 public static boolean isCacheOn() {
117 return _UseCache && ENABLE_CACHE;
118 }
119
120 public static void Precache(String framename) {
121 // if the cache is turned off, do nothing
122 if (!isCacheOn())
123 return;
124
125 // if the frame is already in the cache, do nothing
126 if (_Cache.containsKey(framename.toLowerCase()))
127 return;
128
129 // otherwise, load the frame and put it in the cache
130 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Precaching " + framename + ".");
131
132 // do not display errors encountered to the user
133 // (they will be shown at load time)
134 MessageBay.supressMessages(true);
135 // loading automatically caches the frame is caching is turned on
136 LoadFromDisk(framename, null, false);
137 MessageBay.supressMessages(false);
138 }
139
140 /**
141 * Checks if a string is a representation of a positive integer.
142 *
143 * @param s
144 * @return true if s is a positive integer
145 */
146 public static boolean isPositiveInteger(String s) {
147 if (s == null || s.length() == 0)
148 return false;
149
150 for (int i = 0; i < s.length(); i++) {
151 if (!Character.isDigit(s.charAt(i)))
152 return false;
153 }
154 return true;
155 }
156
157 public static Frame LoadFrame(String frameName) {
158 return LoadFrame(frameName, null, false);
159 }
160
161 public static Frame LoadFrame(String frameName, String path) {
162 return LoadFrame(frameName, path, false);
163 }
164
165 public static Frame LoadFrame(String frameName, String path,
166 boolean ignoreAnnotations) {
167 if (!isValidFrameName(frameName))
168 return null;
169
170 String frameNameLower = frameName.toLowerCase();
171 // first try reading from cache
172 if (isCacheOn() && _Cache.containsKey(frameNameLower)) {
173 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Loading " + frameName
174 + " from cache.");
175 Frame frame = _Cache.get(frameNameLower);
176 return frame;
177 }
178
179 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Loading " + frameName
180 + " from disk.");
181
182 return LoadFromDisk(frameName, path, ignoreAnnotations);
183 }
184
185 public static BufferedReader LoadPublicFrame(String frameName) {
186 String fullPath = FrameIO.getFrameFullPathName(PUBLIC_PATH, frameName);
187
188 if (fullPath == null)
189 return null;
190
191 File frameFile = new File(fullPath);
192 if (frameFile.exists() && frameFile.canRead()) {
193 try {
194 return new BufferedReader(new FileReader(frameFile));
195 } catch (FileNotFoundException e) {
196 e.printStackTrace();
197 }
198 }
199 return null;
200 }
201
202 private static Frame LoadFromDisk(String framename, String knownPath,
203 boolean ignoreAnnotations) {
204 Frame loaded = null;
205
206 if (knownPath != null) {
207 loaded = LoadKnowPath(knownPath, framename);
208 } else {
209
210 for (String path : UserSettings.FrameDirs) {
211 loaded = LoadKnowPath(path, framename);
212 if (loaded != null) {
213 break;
214 }
215 }
216 }
217
218 if (loaded == null && FrameShare.getInstance() != null) {
219 loaded = FrameShare.getInstance().loadFrame(framename, knownPath);
220 }
221
222 if (loaded != null) {
223 FrameUtils.Parse(loaded, true, ignoreAnnotations);
224 }
225
226 return loaded;
227 }
228
229 /**
230 * Gets a list of all the framesets available to the user
231 *
232 * @return a string containing a list of all the available framesets on
233 * separate lines
234 */
235 public static String getFramesetList() {
236 StringBuffer list = new StringBuffer();
237
238 for (String path : UserSettings.FrameDirs) {
239 File files = new File(path);
240 if (!files.exists())
241 continue;
242 for (File f : (new File(path)).listFiles()) {
243 if (f.isDirectory()) {
244 list.append(f.getName()).append('\n');
245 }
246 }
247 }
248 // remove the final new line char
249 list.deleteCharAt(list.length() - 1);
250 return list.toString();
251 }
252
253 /**
254 * Gets the full path and file name of the frame.
255 *
256 * @param path-
257 * the directory in which to look for the frameset containing the
258 * frame.
259 * @param frameName-
260 * the name of the frame for which the path is being requested.
261 * @return null if the frame can not be located.
262 */
263 public static synchronized String getFrameFullPathName(String path,
264 String frameName) {
265 String source = path + Conversion.getFramesetName(frameName)
266 + File.separator;
267
268 File tester = new File(source);
269 if (!tester.exists())
270 return null;
271
272 // check for the new file name format
273 String fullPath = source + Conversion.getFrameNumber(frameName)
274 + ExpReader.EXTENTION;
275 tester = new File(fullPath);
276
277 if (tester.exists())
278 return fullPath;
279
280 // check for oldfile name format
281 fullPath = source + Conversion.getFramesetName(frameName) + "."
282 + Conversion.getFrameNumber(frameName);
283 tester = new File(fullPath);
284
285 if (tester.exists())
286 return fullPath;
287
288 return null;
289 }
290
291 public static boolean canAccessFrame(String frameName) {
292 Frame current = DisplayIO.getCurrentFrame();
293 // Just incase the current frame is not yet saved...
294 if (frameName.equals(current.getName())) {
295 FrameIO.SaveFrame(current, false, false);
296 current.change();
297 return true;
298 }
299
300 for (String path : UserSettings.FrameDirs) {
301 if (getFrameFullPathName(path, frameName) != null)
302 return true;
303 }
304 return false;
305 }
306
307 public static Collection<String> searchFrame(String frameName,
308 String pattern, String path) {
309 String fullPath = null;
310 if (path == null) {
311 for (String possiblePath : UserSettings.FrameDirs) {
312 fullPath = getFrameFullPathName(possiblePath, frameName);
313 if (fullPath != null)
314 break;
315 }
316 } else {
317 fullPath = getFrameFullPathName(path, frameName);
318 }
319 // If the frame was not located return null
320 if (fullPath == null)
321 return null;
322 Collection<String> results = new LinkedList<String>();
323 // Open the file and search the text items
324 try {
325 BufferedReader reader = new BufferedReader(new FileReader(fullPath));
326 String next;
327 while (reader.ready() && ((next = reader.readLine()) != null)) {
328 if (next.startsWith("T")) {
329 String toSearch = next.substring(2);
330 if (toSearch.toLowerCase().contains(pattern))
331 results.add(toSearch);
332 }
333 }
334 } catch (FileNotFoundException e) {
335 e.printStackTrace();
336 return null;
337 } catch (IOException e) {
338 e.printStackTrace();
339 }
340 return results;
341 }
342
343 private static Frame LoadKnowPath(String path, String frameName) {
344 String fullPath = getFrameFullPathName(path, frameName);
345 if (fullPath == null)
346 return null;
347
348 try {
349 FrameReader reader;
350
351 if (fullPath.endsWith(ExpReader.EXTENTION)) {
352 reader = new ExpReader(frameName);
353 } else {
354 reader = new KMSReader();
355 }
356 Frame frame = reader.readFrame(fullPath);
357
358 if (frame == null) {
359 MessageBay.errorMessage("Error: " + frameName
360 + " could not be successfully loaded.");
361 return null;
362 }
363
364 frame.setPath(path);
365
366 // do not put 0 frames or virtual frames into the cache
367 // Why are zero frames not put in the cache
368 if (_Cache.size() > MAX_CACHE)
369 _Cache.clear();
370
371 if (frame.getNumber() > 0 && isCacheOn())
372 _Cache.put(frameName.toLowerCase(), frame);
373
374 return frame;
375 } catch (IOException ioe) {
376 ioe.printStackTrace();
377 Logger.Log(ioe);
378 } catch (Exception e) {
379 e.printStackTrace();
380 Logger.Log(e);
381 MessageBay.errorMessage("Error: " + frameName
382 + " could not be successfully loaded.");
383 }
384
385 return null;
386 }
387
388 public static void Reload() {
389 // disable cache
390 boolean cache = _UseCache;
391
392 _UseCache = false;
393 Frame fresh = FrameIO.LoadFrame(DisplayIO.getCurrentFrame().getName());
394 _UseCache = cache;
395 if (_Cache.containsKey(fresh.getName().toLowerCase()))
396 addToCache(fresh);
397 DisplayIO.setCurrentFrame(fresh, false);
398 }
399
400 public static Frame LoadPrevious(Frame current) {
401 checkTDFC(current);
402
403 // the current name and number
404 String name = current.getFramesetName();
405 int num = current.getNumber() - 1;
406
407 // loop until a frame that exists is found
408 for (; num >= 0; num--) {
409 Frame f = LoadFrame(name + num, current.getPath());
410 if (f != null)
411 return f;
412 }
413
414 // if we did not find another Frame then this one must be the last one
415 // in the frameset
416 MessageBay
417 .displayMessageOnce("This is the first frame in the frameset");
418 return null;
419 }
420
421 /**
422 * Returns the next Frame in the current Frameset (The Frame with the next
423 * highest Frame number) If the current Frame is the last one in the
424 * Frameset, or an error occurs then null is returned.
425 *
426 * @return The Frame after this one in the current frameset, or null
427 */
428 public static Frame LoadNext(Frame current) {
429 checkTDFC(current);
430
431 // the current name and number
432 int num = current.getNumber() + 1;
433 int max = num + 1;
434 String name = current.getFramesetName();
435
436 // read the maximum from the INF file
437 try {
438 max = ReadINF(current.getPath(), current.getFramesetName(), false);
439 } catch (IOException ioe) {
440 MessageBay.errorMessage("Error loading INF file for frameset '"
441 + name + "'");
442 return null;
443 }
444
445 // loop until a frame that exists is found
446 for (; num <= max; num++) {
447 Frame f = LoadFrame(name + num, current.getPath());
448 if (f != null)
449 return f;
450 }
451
452 // if we did not find another Frame then this one must be the last one
453 // in the frameset
454 MessageBay.displayMessageOnce("This is the last frame in the frameset");
455 return null;
456 }
457
458 /**
459 * This method checks if the current frame has just been created with TDFC.
460 * If it has the frame is saved regardless of whether it has been edited or
461 * not and the TDFC item property is cleared. This is to ensure that the
462 * link is saved on the parent frame.
463 *
464 * @param current
465 */
466 public static void checkTDFC(Frame current) {
467 if (FrameUtils.getTdfcItem() != null) {
468 FrameUtils.setTdfcItem(null);
469 current.change();
470 }
471 }
472
473 public static Frame LoadLast(String framesetName, String path) {
474 // read the maximum from the INF file
475 int max;
476 try {
477 max = ReadINF(path, framesetName, false);
478 } catch (IOException ioe) {
479 MessageBay.errorMessage("Error loading INF file for frameset '"
480 + framesetName + "'");
481 return null;
482 }
483
484 // loop backwards until a frame that exists is found
485 for (int num = max; num > 0; num--) {
486 Frame f = LoadFromDisk(framesetName + num, path, false);
487 if (f != null)
488 return f;
489 }
490
491 // if we did not find another Frame then this one must be the last one
492 // in the frameset
493 MessageBay.displayMessage("This is the last frame in the frameset");
494 return null;
495 }
496
497 public static Frame LoadZero(String framesetName, String path) {
498 return LoadFrame(framesetName + 0);
499 }
500
501 public static Frame LoadZero() {
502 Frame current = DisplayIO.getCurrentFrame();
503 return LoadZero(current.getFramesetName(), current.getPath());
504 }
505
506 public static Frame LoadLast() {
507 Frame current = DisplayIO.getCurrentFrame();
508 return LoadLast(current.getFramesetName(), current.getPath());
509 }
510
511 public static Frame LoadNext() {
512 return LoadNext(DisplayIO.getCurrentFrame());
513 }
514
515 public static Frame LoadPrevious() {
516 return LoadPrevious(DisplayIO.getCurrentFrame());
517 }
518
519 /**
520 * Deletes the given Frame on disk and removes the cached Frame if there is
521 * one. Also adds the deleted frame into the deletedFrames frameset.
522 *
523 * @param toDelete
524 * The Frame to be deleted
525 * @return The name the deleted frame was changed to, or null if the delete
526 * failed
527 */
528 public static String DeleteFrame(Frame toDelete) throws IOException,
529 SecurityException {
530 if (toDelete == null)
531 return null;
532
533 // Dont delete the zero frame
534 if (toDelete.getNumber() == 0) {
535 throw new SecurityException("Deleting a zero frame is illegal");
536 }
537
538 // Dont delete the zero frame
539 if (!toDelete.isLocal()) {
540 throw new SecurityException("Attempted to delete remote frame");
541 }
542
543 SaveFrame(toDelete);
544
545 // Copy deleted frames to the DeletedFrames frameset
546 // get the last used frame in the destination frameset
547 final String DELETED_FRAMES = "DeletedFrames";
548 int lastNumber = FrameIO.getLastNumber(DELETED_FRAMES);
549 String framePath;
550 try {
551 // create the new frameset
552 Frame one = FrameIO.CreateFrameset(DELETED_FRAMES, toDelete
553 .getPath());
554 framePath = one.getPath();
555 lastNumber = 0;
556 } catch (Exception e) {
557 Frame zero = FrameIO.LoadFrame(DELETED_FRAMES + "0");
558 framePath = zero.getPath();
559 }
560
561 // get the fill path to determine which file version it is
562 String source = getFrameFullPathName(toDelete.getPath(), toDelete
563 .getName());
564
565 String oldFrameName = toDelete.getName().toLowerCase();
566 // Now save the frame in the new location
567 toDelete.setFrameset(DELETED_FRAMES);
568 toDelete.setFrameNumber(lastNumber + 1);
569 toDelete.setPath(framePath);
570 ForceSaveFrame(toDelete);
571
572 if (_Cache.containsKey(oldFrameName))
573 _Cache.remove(oldFrameName);
574
575 File del = new File(source);
576
577 java.io.FileInputStream ff = new java.io.FileInputStream(del);
578 ff.close();
579
580 if (del.delete()) {
581 return toDelete.getName();
582 }
583
584 return null;
585 }
586
587 /**
588 * Creates a new Frame in the given frameset and assigns it the given Title,
589 * which can be null. The newly created Frame is a copy of the frameset's .0
590 * file with the number updated based on the last recorded Frame name in the
591 * frameset's INF file.
592 *
593 * @param frameset
594 * The frameset to create the new Frame in
595 * @param frameTitle
596 * The title to assign to the newly created Frame (can be NULL).
597 * @return The newly created Frame.
598 */
599 public static synchronized Frame CreateFrame(String frameset,
600 String frameTitle, String templateFrame) throws RuntimeException {
601
602 if (!FrameIO.isValidFramesetName(frameset)) {
603 throw new RuntimeException(frameset
604 + " is not a valid frameset name");
605 }
606
607 int next = -1;
608
609 // disable caching of 0 frames
610 // Mike says: Why is caching of 0 frames being disabled?
611 /*
612 * Especially since 0 frames are not event put into the cache in the
613 * frist place
614 */
615 // SuspendCache();
616 /*
617 * Suspending the cache causes infinate loops when trying to load a zero
618 * frame which has a ao which contains an v or av which contains a link
619 * to the ao frame
620 */
621
622 String zeroFrameName = frameset + "0";
623 Frame destFramesetZero = LoadFrame(zeroFrameName);
624 if (destFramesetZero == null) {
625 throw new RuntimeException(zeroFrameName + " could not be found");
626 }
627
628 Frame template = null;
629 if (templateFrame == null) {
630 // load in frame.0
631 template = destFramesetZero;
632 } else {
633 template = LoadFrame(templateFrame);
634 if (template == null) {
635 throw new RuntimeException("LinkTemplate " + templateFrame
636 + " could not be found");
637 }
638 }
639
640 ResumeCache();
641
642 // read the next number from the INF file
643 try {
644 next = ReadINF(destFramesetZero.getPath(), frameset, true);
645 } catch (IOException ioe) {
646 ioe.printStackTrace();
647 throw new RuntimeException("INF file could not be read");
648 }
649
650 // Remove the old frame from the cashe then add the new one
651 // TODO figure out some way that we can put both in the cache
652 _Cache.remove(template.getName().toLowerCase());
653 // set the number and title of the new frame
654 template.setName(frameset, ++next);
655 template.setTitle(frameTitle);
656 // _Cache.put(template.getName().toLowerCase(), template);
657
658 Logger.Log(Logger.SYSTEM, Logger.TDFC, "Creating new frame: "
659 + template.getName() + " from TDFC");
660
661 template.setOwner(UserSettings.UserName);
662 template.reset();
663 template.resetDateCreated();
664
665 for (Item i : template.getItems()) {
666 if (ItemUtils.startsWithTag(i, ItemUtils.TAG_PARENT))
667 i.setLink(null);
668 }
669
670 // do auto shrinking of the title IF not in twin frames mode
671 Item titleItem = template.getTitleItem();
672
673 if (!DisplayIO.isTwinFramesOn()) {
674 if ((titleItem.getX() + 1) < template.getNameItem().getX()) {
675 while (titleItem.getSize() > Text.MINIMUM_FONT_SIZE
676 && titleItem.getBoundsWidth() + titleItem.getX() > template
677 .getNameItem().getX()) {
678 titleItem.setSize(titleItem.getSize() - 1);
679
680 }
681 } else {
682 System.out.println("Bad title x position: " + titleItem.getX());
683 }
684 }
685
686 // Assign a width to the title.
687 titleItem.setRightMargin(template.getNameItem().getX(), true);
688
689 return template;
690 }
691
692 public static void DisableCache() {
693 _UseCache = false;
694 }
695
696 public static void EnableCache() {
697 _UseCache = true;
698 }
699
700 public static void SuspendCache() {
701 if (_UseCache) {
702 DisableCache();
703 _SuspendedCache = true;
704 } else {
705 _SuspendedCache = false;
706 }
707 }
708
709 public static void ResumeCache() {
710 if (_SuspendedCache) {
711 EnableCache();
712 _SuspendedCache = false;
713 }
714 }
715
716 public static void RefreshCasheImages() {
717 SuspendCache();
718 for (Frame f : _Cache.values())
719 f.setBuffer(null);
720 ResumeCache();
721 }
722
723 /**
724 * Creates a new frameset using the given name. This includes creating a new
725 * subdirectory in the <code>FRAME_PATH</code> directory, Copying over the
726 * default.0 frame from the default frameset, copying the .0 Frame to make a
727 * .1 Frame, and creating the frameset's INF file.
728 *
729 * @param frameset
730 * The name of the Frameset to create
731 * @return The first Frame of the new Frameset (Frame.1)
732 */
733 public static Frame CreateFrameset(String frameset, String path)
734 throws Exception {
735 return CreateFrameset(frameset, path, false);
736 }
737
738 /**
739 * Tests if the given String is a 'proper' framename, that is, the String
740 * must begin with a character, end with a number with 0 or more letters and
741 * numbers in between.
742 *
743 * @param frameName
744 * The String to test for validity as a frame name
745 * @return True if the given framename is proper, false otherwise.
746 */
747 public static boolean isValidFrameName(String frameName) {
748
749 if (frameName == null || frameName.length() < 2)
750 return false;
751
752 int lastCharIndex = frameName.length() - 1;
753 // String must begin with a letter and end with a digit
754 if (!Character.isLetter(frameName.charAt(0))
755 || !Character.isDigit(frameName.charAt(lastCharIndex)))
756 return false;
757
758 // All the characters between first and last must be letters
759 // or digits
760 for (int i = 1; i < lastCharIndex; i++) {
761 if (!isValidFrameNameChar(frameName.charAt(i)))
762 return false;
763 }
764 return true;
765 }
766
767 private static boolean isValidFrameNameChar(char c) {
768 return Character.isLetterOrDigit(c) || c == '-';
769 }
770
771 /**
772 * Saves the given Frame to disk in the corresponding frameset directory.
773 * This is the same as calling SaveFrame(toSave, true)
774 *
775 * @param toSave
776 * The Frame to save to disk
777 */
778 public static String SaveFrame(Frame toSave) {
779 return SaveFrame(toSave, true);
780 }
781
782 /**
783 * Saves a frame.
784 *
785 * @param toSave
786 * the frame to save
787 * @param inc
788 * true if the frames counter should be incremented
789 * @return the text content of the frame
790 */
791 public static String SaveFrame(Frame toSave, boolean inc) {
792 return SaveFrame(toSave, inc, true);
793 }
794
795 /**
796 * Saves the given Frame to disk in the corresponding frameset directory, if
797 * inc is true then the saved frames counter is incremented, otherwise it is
798 * untouched.
799 *
800 * @param toSave
801 * The Frame to save to disk
802 * @param inc
803 * True if the saved frames counter should be incremented, false
804 * otherwise.
805 * @param checkBackup
806 * True if the frame should be checked for the back up tag
807 */
808 public static String SaveFrame(Frame toSave, boolean inc,
809 boolean checkBackup) {
810
811 // TODO When loading a frame maybe append onto the event history too-
812 // with a
813 // break to indicate the end of a session
814
815 if (toSave == null || !toSave.hasChanged() || toSave.isSaved()) {
816 return "";
817 }
818
819 // Dont save if the frame is protected and it exists
820 if (checkBackup && toSave.isReadOnly()) {
821 _Cache.remove(toSave.getName().toLowerCase());
822 return "";
823 }
824
825 /* Dont save the frame if it has the noSave tag */
826 if (toSave.hasAnnotation("nosave")) {
827 Actions.PerformActionCatchErrors(toSave, null, "Restore");
828 return "";
829 }
830
831 // Save frame that is not local through the Networking classes
832 // TODO
833 if (!toSave.isLocal()) {
834 return FrameShare.getInstance().saveFrame(toSave);
835 }
836
837 /* Format the frame if it has the autoFormat tag */
838 if (toSave.hasAnnotation("autoformat")) {
839 Actions.PerformActionCatchErrors(toSave, null, "Format");
840 }
841
842 /**
843 * Get the full path only to determine which format to use for saving
844 * the frame. At this stage use Exp format for saving Exp frames only.
845 * Later this will be changed so that KMS frames will be updated to the
846 * Exp format.
847 */
848 String fullPath = getFrameFullPathName(toSave.getPath(), toSave
849 .getName());
850
851 // Check if the frame exists
852 if (checkBackup && fullPath == null) {
853 // The first time a frame with the backup tag is saved, dont back it
854 // up
855 checkBackup = false;
856 }
857
858 FrameWriter writer = null;
859 int savedVersion;
860 try {
861 // if its a new frame or an existing Exp frame...
862 if (fullPath == null || fullPath.endsWith(ExpReader.EXTENTION)) {
863 writer = new ExpWriter();
864 savedVersion = ExpReader.getVersion(fullPath);
865 } else {
866 writer = new KMSWriter();
867 savedVersion = KMSReader.getVersion(fullPath);
868 }
869
870 // Check if the frame doesnt exist
871 // if (savedVersion < 0) {
872 // /*
873 // * This will happen if the user has two Expeditee's running at
874 // * once and closes the first. When the second one closes the
875 // * messages directory will have been deleted.
876 // */
877 // MessageBay
878 // .errorMessage("Could not save frame that does not exist: "
879 // + toSave.getName());
880 // return null;
881 // }
882
883 // Check if we are trying to save an out of date version
884 if (savedVersion > toSave.getVersion()
885 && !toSave.getFramesetName().equalsIgnoreCase(
886 MessageBay.MESSAGES_FRAMESET_NAME)) {
887 // remove this frame from the cache if it is there
888 // This will make sure links to the original are set correctly
889 _Cache.remove(toSave.getName().toLowerCase());
890 int nextnum = ReadINF(toSave.getPath(), toSave
891 .getFramesetName(), false) + 1;
892 SuspendCache();
893 Frame original = LoadFrame(toSave.getName());
894 toSave.setFrameNumber(nextnum);
895 ResumeCache();
896 // Put the modified version in the cache
897 addToCache(toSave);
898 // Show the messages alerting the user
899 Text originalMessage = new Text(-1);
900 originalMessage.setColor(MessageBay.ERROR_COLOR);
901 originalMessage.setText(original.getName()
902 + " was updated by another user.");
903 originalMessage.setLink(original.getName());
904 Text yourMessage = new Text(-1);
905 yourMessage.setColor(MessageBay.ERROR_COLOR);
906 yourMessage.setText("Your version was renamed "
907 + toSave.getName());
908 yourMessage.setLink(toSave.getName());
909 MessageBay.displayMessage(originalMessage);
910 MessageBay.displayMessage(yourMessage);
911 } else if (checkBackup
912 && ItemUtils.ContainsExactTag(toSave.getItems(),
913 ItemUtils.TAG_BACKUP)) {
914 SuspendCache();
915 String oldFramesetName = toSave.getFramesetName() + "-old";
916
917 Frame original = LoadFrame(toSave.getName());
918 if (original == null)
919 original = toSave;
920 int orignum = original.getNumber();
921
922 int nextnum = -1;
923 try {
924 nextnum = ReadINF(toSave.getPath(), oldFramesetName, false) + 1;
925 } catch (RuntimeException e) {
926 try {
927 CreateFrameset(oldFramesetName, toSave.getPath());
928 nextnum = 1;
929 } catch (Exception e1) {
930 e1.printStackTrace();
931 }
932 //e.printStackTrace();
933 }
934
935 if (nextnum > 0) {
936 original.setFrameset(oldFramesetName);
937 original.setFrameNumber(nextnum);
938 original.setPermission(Permission.copy);
939 original.change();
940 SaveFrame(original, false, false);
941 }
942
943 Item i = ItemUtils.FindExactTag(toSave.getItems(),
944 ItemUtils.TAG_BACKUP);
945 i.setLink(original.getName());
946 toSave.setFrameNumber(orignum);
947 ResumeCache();
948 }
949 // Update general stuff about frame
950 setSavedProperties(toSave);
951
952 // int oldMode = FrameGraphics.getMode();
953 // if (oldMode != FrameGraphics.MODE_XRAY)
954 // FrameGraphics.setMode(FrameGraphics.MODE_XRAY, true);
955 writer.writeFrame(toSave);
956 // FrameGraphics.setMode(oldMode, true);
957 toSave.setSaved();
958 if (inc) {
959 SessionStats.SavedFrame(toSave.getName());
960 }
961
962 // avoid out-of-sync frames (when in TwinFrames mode)
963 if (_Cache.containsKey(toSave.getName().toLowerCase()))
964 addToCache(toSave);
965
966 Logger.Log(Logger.SYSTEM, Logger.SAVE, "Saving " + toSave.getName()
967 + " to disk.");
968
969 // check that the INF file is not out of date
970 int last = ReadINF(toSave.getPath(), toSave.getFramesetName(),
971 false);
972 if (last <= toSave.getNumber())
973 WriteINF(toSave.getPath(), toSave.getFramesetName(), toSave
974 .getName());
975
976 // check if this was the profile frame (and thus needs
977 // re-parsing)
978 if (isProfileFrame(toSave)) {
979 Frame profile = FrameIO.LoadFrame(toSave.getFramesetName()
980 + "1");
981 assert (profile != null);
982 FrameUtils.ParseProfile(profile);
983 }
984 } catch (IOException ioe) {
985 ioe.printStackTrace();
986 ioe.getStackTrace();
987 Logger.Log(ioe);
988 return null;
989 }
990
991 return writer.getFileContents();
992 }
993
994 /**
995 * @param toAdd
996 */
997 public static void addToCache(Frame toAdd) {
998 _Cache.put(toAdd.getName().toLowerCase(), toAdd);
999 }
1000
1001 /**
1002 * Checks if a frame is in the current user profile frameset.
1003 *
1004 * @param toCheck
1005 * the frame to check
1006 * @return true if the frame is in the current user profile frameset
1007 */
1008 public static boolean isProfileFrame(Frame toCheck) {
1009 if (toCheck.getNumber() == 0)
1010 return false;
1011 return toCheck.getPath().equals(PROFILE_PATH);
1012 // return toCheck.getFramesetName()
1013 // .equalsIgnoreCase(UserSettings.ProfileName);
1014 }
1015
1016 public static Frame LoadProfile(String userName) {
1017 return LoadFrame(userName + "1");
1018 }
1019
1020 public static Frame CreateNewProfile(String username) throws Exception {
1021 Frame profile = CreateFrameset(username, PROFILE_PATH, true);
1022 FrameUtils.CreateDefaultProfile(username, profile);
1023 return profile;
1024 }
1025
1026 /**
1027 * Reads the INF file that corresponds to the given Frame name
1028 *
1029 * @param framename
1030 * The Frame to lookup the INF file for
1031 * @throws IOException
1032 * Any exceptions encountered by the BufferedReader used to read
1033 * the INF.
1034 */
1035 public static int ReadINF(String path, String frameset, boolean update)
1036 throws IOException {
1037 assert (!frameset.endsWith("."));
1038 try {
1039 // read INF
1040 BufferedReader reader;
1041 try {
1042 // Check on the local drive
1043 reader = new BufferedReader(new FileReader(path
1044 + frameset.toLowerCase() + File.separator
1045 + INF_FILENAME));
1046 } catch (Exception e) {
1047 reader = new BufferedReader(new FileReader(path
1048 + frameset.toLowerCase() + File.separator
1049 + frameset.toLowerCase() + ".inf"));
1050 }
1051 String inf = reader.readLine();
1052 reader.close();
1053
1054 int next = Conversion.getFrameNumber(inf);
1055 // update INF file
1056 if (update) {
1057 try {
1058 WriteINF(path, frameset, frameset + (next + 1));
1059 } catch (IOException ioe) {
1060 ioe.printStackTrace();
1061 Logger.Log(ioe);
1062 }
1063 }
1064 return next;
1065 } catch (Exception e) {
1066 }
1067
1068 // Check peers
1069 return FrameShare.getInstance().getInfNumber(path, frameset, update);
1070 }
1071
1072 /**
1073 * Writes the given String out to the INF file corresponding to the current
1074 * frameset.
1075 *
1076 * @param toWrite
1077 * The String to write to the file.
1078 * @throws IOException
1079 * Any exception encountered by the BufferedWriter.
1080 */
1081 public static void WriteINF(String path, String frameset, String frameName)
1082 throws IOException {
1083 try {
1084 assert (!frameset.endsWith("."));
1085
1086 path += frameset.toLowerCase() + File.separator + INF_FILENAME;
1087
1088 BufferedWriter writer = new BufferedWriter(new FileWriter(path));
1089 writer.write(frameName);
1090 writer.close();
1091 } catch (Exception e) {
1092
1093 }
1094 }
1095
1096 public static boolean FrameIsCached(String name) {
1097 return _Cache.containsKey(name);
1098 }
1099
1100 /**
1101 * Gets a frame from the cache.
1102 *
1103 * @param name
1104 * The frame to get from the cache
1105 *
1106 * @return The frame from cache. Null if not cached.
1107 */
1108 public static Frame FrameFromCache(String name) {
1109 return _Cache.get(name);
1110 }
1111
1112 public static String ConvertToValidFramesetName(String toValidate) {
1113 assert (toValidate != null && toValidate.length() > 0);
1114
1115 StringBuffer result = new StringBuffer();
1116
1117 if (Character.isDigit(toValidate.charAt(0))) {
1118 result.append(FRAME_NAME_LAST_CHAR);
1119 }
1120
1121 boolean capital = false;
1122 for (int i = 0; i < toValidate.length()
1123 && result.length() < MAX_NAME_LENGTH; i++) {
1124 char cur = toValidate.charAt(i);
1125
1126 // capitalize all characters after spaces
1127 if (Character.isLetterOrDigit(cur)) {
1128 if (capital) {
1129 capital = false;
1130 result.append(Character.toUpperCase(cur));
1131 } else
1132 result.append(cur);
1133 } else {
1134 capital = true;
1135 }
1136 }
1137 assert (result.length() > 0);
1138 int lastCharIndex = result.length() - 1;
1139 if (!Character.isLetter(result.charAt(lastCharIndex))) {
1140 if (lastCharIndex == MAX_NAME_LENGTH - 1)
1141 result.setCharAt(lastCharIndex, FRAME_NAME_LAST_CHAR);
1142 else
1143 result.append(FRAME_NAME_LAST_CHAR);
1144 }
1145
1146 assert (isValidFramesetName(result.toString()));
1147 return result.toString();
1148 }
1149
1150 public static Frame CreateNewFrame(Item linker) throws RuntimeException {
1151 String title = linker.getName();
1152
1153 String templateLink = linker.getAbsoluteLinkTemplate();
1154 String framesetLink = linker.getAbsoluteLinkFrameset();
1155 String frameset = (framesetLink != null ? framesetLink : DisplayIO
1156 .getCurrentFrame().getFramesetName());
1157
1158 Frame newFrame = FrameIO.CreateFrame(frameset, title, templateLink);
1159 return newFrame;
1160 }
1161
1162 /**
1163 * Creates a new Frameset on disk, including a .0, .1, and .inf files. The
1164 * Default.0 frame is copied to make the initial .0 and .1 Frames
1165 *
1166 * @param name
1167 * The Frameset name to use
1168 * @return The name of the first Frame in the newly created Frameset (the .1
1169 * frame)
1170 */
1171 public static Frame CreateNewFrameset(String name) throws Exception {
1172 String path = DisplayIO.getCurrentFrame().getPath();
1173
1174 // if current frameset is profile directory change it to framesets
1175 if (path.equals(FrameIO.PROFILE_PATH)) {
1176 path = FrameIO.FRAME_PATH;
1177 }
1178
1179 return FrameIO.CreateFrameset(name, path);
1180 }
1181
1182 /**
1183 *
1184 * @param frameset
1185 * @return
1186 */
1187 public static int getLastNumber(String frameset) { // Rob thinks it might
1188 // have been
1189 // GetHighestNumExFrame
1190 // TODO minimise the number of frames being read in!!
1191 int num = -1;
1192
1193 Frame zero = LoadFrame(frameset + "0");
1194
1195 // the frameset does not exist (or has no 0 frame)
1196 if (zero == null)
1197 return -1;
1198
1199 try {
1200 num = ReadINF(zero.getPath(), frameset, false);
1201 } catch (IOException e) {
1202 // TODO Auto-generated catch block
1203 // e.printStackTrace();
1204 }
1205
1206 /*
1207 * Michael doesnt think the code below is really needed... it will just
1208 * slow things down when we are reading frames over a network***** for (;
1209 * num >= 0; num--) { System.out.println("This code is loading frames to
1210 * find the highest existing frame..."); if (LoadFrame(frameset + num) !=
1211 * null) break; }
1212 */
1213
1214 return num;
1215 }
1216
1217 /**
1218 * Checks if a given frameset is accessable.
1219 *
1220 * @param framesetName
1221 * @return
1222 */
1223 public static Boolean canAccessFrameset(String framesetName) {
1224 framesetName = framesetName.toLowerCase();
1225 for (String path : UserSettings.FrameDirs) {
1226 if ((new File(path + framesetName)).exists())
1227 return true;
1228 }
1229 return false;
1230 }
1231
1232 public static Frame CreateFrameset(String frameset, String path,
1233 boolean recreate) throws Exception {
1234 String conversion = frameset + " --> ";
1235
1236 if (!isValidFramesetName(frameset)) {
1237 throw new Exception("Invalid frameset name");
1238 }
1239
1240 if (!recreate && FrameIO.canAccessFrameset(frameset)) {
1241 throw new ExistingFramesetException(frameset);
1242 }
1243
1244 conversion += frameset;
1245 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Frameset Name: "
1246 + conversion);
1247 conversion = frameset;
1248
1249 /**
1250 * TODO: Update this to exclude any\all invalid filename characters
1251 */
1252 // ignore annotation character
1253 if (frameset.startsWith("@"))
1254 frameset = frameset.substring(1);
1255
1256 conversion += " --> " + frameset;
1257 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Name: " + conversion);
1258
1259 // create the new Frameset directory
1260 File dir = new File(path + frameset.toLowerCase() + File.separator);
1261
1262 dir.mkdirs();
1263
1264 // create the new INF file
1265 try {
1266 WriteINF(path, frameset, frameset + '1');
1267 } catch (IOException ioe) {
1268 ioe.printStackTrace();
1269 Logger.Log(ioe);
1270 }
1271
1272 SuspendCache();
1273 // copy the default .0 and .1 files
1274 Frame base = null;
1275 try {
1276 base = LoadFrame(UserSettings.DefaultFrame);
1277 } catch (Exception e) {
1278 }
1279 // The frame may not be accessed for various reasons... in all these
1280 // cases just create a new one
1281 if (base == null) {
1282 base = new Frame();
1283 }
1284
1285 ResumeCache();
1286
1287 base.reset();
1288 base.resetDateCreated();
1289 base.setFrameset(frameset);
1290 base.setFrameNumber(0);
1291 base.setTitle(base.getFramesetName() + "0");
1292 base.setPath(path);
1293 base.change();
1294 base.setOwner(UserSettings.UserName);
1295 SaveFrame(base, false);
1296
1297 base.reset();
1298 base.resetDateCreated();
1299 base.setFrameNumber(1);
1300 base.setTitle(frameset);
1301 base.change();
1302 base.setOwner(UserSettings.UserName);
1303 SaveFrame(base, true);
1304
1305 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Created new frameset: "
1306 + frameset);
1307
1308 return base;
1309 }
1310
1311 /**
1312 * Tests if a frameset name is valid. That is it must begin and end with a
1313 * letter and contain only letters and digits in between.
1314 *
1315 * @param frameset
1316 * the name to be tested
1317 * @return true if the frameset name is valid
1318 */
1319 public static boolean isValidFramesetName(String frameset) {
1320 if (frameset == null) {
1321 return false;
1322 }
1323
1324 int nameLength = frameset.length();
1325 if (frameset.length() <= 0 || nameLength > MAX_NAME_LENGTH) {
1326 return false;
1327 }
1328
1329 int lastCharIndex = nameLength - 1;
1330
1331 if (!Character.isLetter(frameset.charAt(0))
1332 || !Character.isLetter(frameset.charAt(lastCharIndex)))
1333 return false;
1334
1335 for (int i = 1; i < lastCharIndex; i++) {
1336 if (!isValidFrameNameChar(frameset.charAt(i))) {
1337 return false;
1338 }
1339 }
1340 return true;
1341 }
1342
1343 public static boolean deleteFrameset(String framesetName) {
1344 return moveFrameset(framesetName, FrameIO.TRASH_PATH);
1345 }
1346
1347 public static boolean moveFrameset(String framesetName,
1348 String destinationFolder) {
1349 if (!FrameIO.canAccessFrameset(framesetName))
1350 return false;
1351 // Clear the cache
1352 _Cache.clear();
1353
1354 // Search all the available directories for the directory
1355 for (String path : UserSettings.FrameDirs) {
1356 String source = path + framesetName.toLowerCase() + File.separator;
1357 File framesetDirectory = new File(source);
1358 // Once we have found the directory move it
1359 if (framesetDirectory.exists()) {
1360 String destPath = destinationFolder
1361 + framesetName.toLowerCase();
1362 int copyNumber = 1;
1363 File dest = new File(destPath + File.separator);
1364 // Create the destination folder if it doesnt already exist
1365 if (!dest.getParentFile().exists())
1366 dest.mkdirs();
1367 // If a frameset with the same name is already in the
1368 // destination add
1369 // a number to the end
1370 while (dest.exists()) {
1371 dest = new File(destPath + ++copyNumber + File.separator);
1372 }
1373 if (!framesetDirectory.renameTo(dest)) {
1374 for (File f : framesetDirectory.listFiles()) {
1375 if (!f.delete())
1376 return false;
1377 }
1378 if (!framesetDirectory.delete())
1379 return false;
1380 }
1381 return true;
1382 }
1383 }
1384 return false;
1385 }
1386
1387 public static boolean CopyFrameset(String framesetToCopy,
1388 String copiedFrameset) throws Exception {
1389 if (!FrameIO.canAccessFrameset(framesetToCopy))
1390 return false;
1391 if (FrameIO.canAccessFrameset(copiedFrameset))
1392 return false;
1393 // search through all the directories to find the frameset we are
1394 // copying
1395 for (String path : UserSettings.FrameDirs) {
1396 String source = path + framesetToCopy.toLowerCase()
1397 + File.separator;
1398 File framesetDirectory = new File(source);
1399 if (framesetDirectory.exists()) {
1400 // copy the frameset
1401 File copyFramesetDirectory = new File(path
1402 + copiedFrameset.toLowerCase() + File.separator);
1403 if (!copyFramesetDirectory.mkdirs())
1404 return false;
1405 // copy each of the frames
1406 for (File f : framesetDirectory.listFiles()) {
1407 // Ignore hidden files
1408 if (f.getName().charAt(0) == '.')
1409 continue;
1410 String copyPath = copyFramesetDirectory.getAbsolutePath()
1411 + File.separator + f.getName();
1412 FrameIO.copyFile(f.getAbsolutePath(), copyPath);
1413 }
1414 return true;
1415 }
1416 }
1417 return false;
1418 }
1419
1420 /**
1421 * Copies a file from one location to another.
1422 *
1423 * @param existingFile
1424 * @param newFileName
1425 * @throws Exception
1426 */
1427 public static void copyFile(String existingFile, String newFileName)
1428 throws Exception {
1429 FileInputStream is = new FileInputStream(existingFile);
1430 FileOutputStream os = new FileOutputStream(newFileName, false);
1431 int data;
1432 while ((data = is.read()) != -1) {
1433 os.write(data);
1434 }
1435 os.flush();
1436 os.close();
1437 is.close();
1438 }
1439
1440 /**
1441 * Saves a frame regardless of whether or not the frame is marked as having
1442 * been changed.
1443 *
1444 * @param frame
1445 * the frame to save
1446 * @return the contents of the frame or null if it could not be saved
1447 */
1448 public static String ForceSaveFrame(Frame frame) {
1449 frame.change();
1450 return SaveFrame(frame, false);
1451 }
1452
1453 public static boolean isValidLink(String frameName) {
1454 return frameName == null || isPositiveInteger(frameName)
1455 || isValidFrameName(frameName);
1456 }
1457
1458 public static void SavePublicFrame(String peerName, String frameName,
1459 int version, BufferedReader packetContents) {
1460 // TODO handle versioning - add version to the header
1461 // Remote user uploads version based on an old version
1462
1463 // Remove it from the cache so that next time it is loaded we get the up
1464 // todate version
1465 _Cache.remove(frameName.toLowerCase());
1466
1467 // Save to file
1468 String filename = PUBLIC_PATH + Conversion.getFramesetName(frameName)
1469 + File.separator + Conversion.getFrameNumber(frameName)
1470 + ExpReader.EXTENTION;
1471
1472 File file = new File(filename);
1473 // Ensure the file exists
1474 if (file.exists()) {
1475 // Check the versions
1476 int savedVersion = ExpReader.getVersion(filename);
1477
1478 if (savedVersion > version) {
1479 // remove this frame from the cache if it is there
1480 // This will make sure links to the original are set correctly
1481 // _Cache.remove(frameName.toLowerCase());
1482
1483 int nextNum = 0;
1484 try {
1485 nextNum = ReadINF(PUBLIC_PATH, Conversion
1486 .getFramesetName(frameName), false) + 1;
1487 } catch (IOException e) {
1488 e.printStackTrace();
1489 }
1490
1491 String newName = Conversion.getFramesetName(frameName)
1492 + nextNum;
1493 filename = PUBLIC_PATH + Conversion.getFramesetName(frameName)
1494 + File.separator + nextNum + ExpReader.EXTENTION;
1495
1496 // Show the messages alerting the user
1497 Text originalMessage = new Text(-1);
1498 originalMessage.setColor(MessageBay.ERROR_COLOR);
1499 originalMessage.setText(frameName + " was edited by "
1500 + peerName);
1501 originalMessage.setLink(frameName);
1502 Text yourMessage = new Text(-1);
1503 yourMessage.setColor(MessageBay.ERROR_COLOR);
1504 yourMessage.setText("Their version was renamed " + newName);
1505 yourMessage.setLink(newName);
1506 MessageBay.displayMessage(originalMessage);
1507 MessageBay.displayMessage(yourMessage);
1508
1509 Frame editedFrame = FrameIO.LoadFrame(frameName);
1510
1511 FrameShare.getInstance().sendMessage(
1512 frameName + " was recently edited by "
1513 + editedFrame.getLastModifyUser(), peerName);
1514 FrameShare.getInstance().sendMessage(
1515 "Your version was renamed " + newName, peerName);
1516 }
1517 }
1518
1519 // Save the new version
1520 try {
1521 // FileWriter fw = new FileWriter(file);
1522
1523 // Open an Output Stream Writer to set encoding
1524 OutputStream fout = new FileOutputStream(file);
1525 OutputStream bout = new BufferedOutputStream(fout);
1526 Writer fw = new OutputStreamWriter(bout, "UTF-8");
1527
1528 String nextLine = null;
1529 while ((nextLine = packetContents.readLine()) != null) {
1530 fw.write(nextLine + '\n');
1531 }
1532 fw.flush();
1533 fw.close();
1534 MessageBay.displayMessage("Saved remote frame: " + frameName);
1535 } catch (IOException e) {
1536 MessageBay.errorMessage("Error remote saving " + frameName + ": "
1537 + e.getMessage());
1538 e.printStackTrace();
1539 }
1540 // } else {
1541 //
1542 //
1543 //
1544 // MessageBay
1545 // .errorMessage("Recieved save request for unknown public frame: "
1546 // + frameName);
1547 // }
1548 }
1549
1550 public static void setSavedProperties(Frame toSave) {
1551 toSave.setLastModifyDate(Formatter.getDateTime());
1552 toSave.setLastModifyUser(UserSettings.UserName);
1553 toSave.setVersion(toSave.getVersion() + 1);
1554 Time darkTime = new Time(SessionStats.getFrameDarkTime().getTime()
1555 + toSave.getDarkTime().getTime());
1556 Time activeTime = new Time(SessionStats.getFrameActiveTime().getTime()
1557 + toSave.getActiveTime().getTime());
1558 toSave.setDarkTime(darkTime);
1559 toSave.setActiveTime(activeTime);
1560 }
1561
1562}
Note: See TracBrowser for help on using the repository browser.