Skip to content

Commit

Permalink
merge version3 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-hoffman committed Aug 23, 2015
2 parents 39a4e74 + 7a33e4d commit 4b8c183
Show file tree
Hide file tree
Showing 16 changed files with 563 additions and 65 deletions.
6 changes: 3 additions & 3 deletions ResearchManagementSystem/build_info.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Fri, 21 Aug 2015 17:44:15 -0500
#Sun, 23 Aug 2015 15:05:36 -0500

build.major.number=02
build.minor.number=03
build.major.number=03
build.minor.number=01
Binary file not shown.
Binary file not shown.
73 changes: 45 additions & 28 deletions ResearchManagementSystem/src/rms/control/Loader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package rms.control;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
Expand All @@ -19,45 +20,58 @@ public class Loader {

private static final Logger thisLog = Logger.getLogger(Loader.class.getName());

private static final String stateFileFullPath;
private static final String currentVersionStateFileFullPath;

static {
// setup the currentVersionStateFileFullPath variable
String baseDir = System.getProperty("user.dir");
String fileName = String.format("index_%s.rms", Loader.class.getPackage().getSpecificationVersion());
if (baseDir == null) {
thisLog.log(Level.SEVERE, "Unable to determine user directory.");
stateFileFullPath = null;
currentVersionStateFileFullPath = null;
} else {
stateFileFullPath = baseDir.concat("/").concat(fileName);
currentVersionStateFileFullPath = baseDir.concat("/").concat(fileName);
}
}

/**
* Attempts to deserialize the stored {@code State} from file
* Attempts to deserialize the stored {@code State} from the default path
* for the current version. Exception is thrown if the file does not exist.
*
* @return the {@code State} object stored in file or null if unable to
* deserialize
*
* @throws rms.control.Loader.SerializedStateOutdatedException
* @see rms.model.State
*/
public static synchronized State loadFromFile() {
if (stateFileFullPath == null) {
return null;
public static synchronized State attemptLoadDefaultFromFile() throws SerializedStateOutdatedException {
File stateFile = new File(currentVersionStateFileFullPath);
if (currentVersionStateFileFullPath == null || !stateFile.exists()) {
throw new SerializedStateOutdatedException();
}

State retVal;
return loadFromFile(stateFile);
}

/**
* Deserializes the stored {@code State} from the given path migrating the
* given State to the newest version if it is outdated.
*
* @param stateFile
* @return
*/
public static synchronized State loadFromFile(File stateFile) {
State retVal = null;
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new FileInputStream(stateFileFullPath));
in = new ObjectInputStream(new FileInputStream(stateFile));
retVal = (State) in.readObject();
thisLog.log(Level.FINE, "State loaded from file {0}", stateFileFullPath);
} catch (IOException | ClassNotFoundException ex) {
thisLog.log(Level.INFO, "Unable to load state. Creating new.", ex);
thisLog.log(Level.FINE, "State loaded from file {0}", stateFile.getAbsolutePath());
} catch (Exception ex) { //catch any exception
thisLog.log(Level.INFO, "Unable to load state from " + stateFile.getAbsolutePath() + ". Creating new.", ex);
retVal = new State();
} finally {
Helpers.closeResource(in);
}

return retVal;
}

Expand All @@ -71,22 +85,25 @@ public static synchronized State loadFromFile() {
* @see rms.model.State
*/
public static synchronized boolean storeToFile(State state) {
if (stateFileFullPath == null) {
return false;
}
boolean success = false;

ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream(stateFileFullPath));
out.writeObject(state);
} catch (IOException ex) {
thisLog.log(Level.SEVERE, "Unable to store state.", ex);
return false;
} finally {
Helpers.closeResource(out);
if (currentVersionStateFileFullPath != null) {
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream(currentVersionStateFileFullPath));
out.writeObject(state);
thisLog.log(Level.FINE, "State saved to file {0}", currentVersionStateFileFullPath);
success = true;
} catch (IOException ex) {
thisLog.log(Level.SEVERE, "Unable to store state.", ex);
} finally {
Helpers.closeResource(out);
}
}
return success;
}

public static class SerializedStateOutdatedException extends Exception {

thisLog.log(Level.FINE, "State saved to file {0}", stateFileFullPath);
return true;
}
}
13 changes: 11 additions & 2 deletions ResearchManagementSystem/src/rms/control/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import rms.model.item.ItemFactory;
import rms.model.item.ItemThread;
import rms.view.MainFrame;
import rms.view.util.Prompts;

/**
*
Expand Down Expand Up @@ -78,7 +79,15 @@ private static void setupLogging() {
* @return true iff loading was successful
*/
public static boolean loadStateFromFile() {
state = Loader.loadFromFile();
try {
state = Loader.attemptLoadDefaultFromFile();
} catch (Loader.SerializedStateOutdatedException ex) {
Prompts.informUser("Data file not found", "The data file cannot be found. This may be the result of a recent program update. Please select a data file to load.", Prompts.PromptType.WARNING);
JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
if (chooser.showOpenDialog(gui) == JFileChooser.APPROVE_OPTION) {
state = Loader.loadFromFile(chooser.getSelectedFile());
}
}
return state != null;
}

Expand All @@ -92,7 +101,7 @@ public static boolean storeStateToFile() {
}

public static void deleteThread() {
state.getThreads().remove(gui.getSelectedThread());
state.deleteThread(gui.getSelectedThread());
gui.refreshThreadListAndDisplay();
gui.clearSelectedThread();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ protected boolean accept(Item i) {

@Override
protected boolean accept(ItemThread t) {
return !Helpers.intersection(t.getTags(), tag).isEmpty();
return !Helpers.intersection(t.getTagsUnmodifible(), tag).isEmpty();
}
}
159 changes: 140 additions & 19 deletions ResearchManagementSystem/src/rms/model/State.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package rms.model;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import rms.model.item.ItemThread;
Expand All @@ -15,16 +17,20 @@ public class State implements Serializable {

private static final long serialVersionUID = 01L;

// Used for serialization backwards compatibility. Should be updated if
// serialization incompatible changes are made. Also update the
// deserialization process outlined at the end of this file.
private byte classSerializationVersion;

// State data
private int nextItemNumber;
private int nextThreadNumber;
private final Set<ItemThread> threads;
private final Set<Tag> tags;
private ThreadTagMap threadsAndTags;

public State() {
nextItemNumber = 0;
nextThreadNumber = 0;
threads = new HashSet<>();
tags = new HashSet<>();
threadsAndTags = new ThreadTagMap();
}

public int getNextItemNumber() {
Expand All @@ -35,43 +41,158 @@ public int getNextThreadNumber() {
return ++nextThreadNumber;
}

/**
* Creates a new {@link ItemThread}, adds it to the State, and returns it.
*
* @return
*/
public ItemThread createNewThread() {
ItemThread t = new ItemThread();
this.threads.add(t);
threadsAndTags.addNewThread(t);
return t;
}

public Set<ItemThread> getThreads() {
return threads;
}

public Set<Tag> getTagsUnmodifiable() {
return Collections.unmodifiableSet(tags);
/**
* Permanently delete the given {@link ItemThread} from the State.
*
* @param threadToRemove
*/
public void deleteThread(ItemThread threadToRemove) {
threadsAndTags.deleteItemThread(threadToRemove);
}

/**
* Creates a new {@link Tag} with the given name, adds it to the State, and
* returns the new Tag.
* returns it.
*
* @param name
* @return
*/
public Tag newTag(String name) {
public Tag createNewTag(String name) {
Tag t = new Tag(name);
tags.add(t);
threadsAndTags.addNewTag(t);
return t;
}

/**
* Permanantly delete the given {@link Tag}s from the State (including from
* Permanently delete the given {@link Tag}s from the State (including from
* all {@link ItemThread}s which reference the Tags).
*
* @param tagsToDelete
*/
public void deleteTags(Set<Tag> tagsToDelete) {
tags.removeAll(tagsToDelete);
for (ItemThread t : threads) {
t.getTags().removeAll(tagsToDelete);
for (Tag t : tagsToDelete) {
threadsAndTags.deleteTag(t);
}
}

public void addTagToThread(ItemThread thread, Tag tag) {
threadsAndTags.addTagToThread(thread, tag);
}

public void removeTagFromThread(ItemThread thread, Tag tag) {
threadsAndTags.removeTagFromThread(thread, tag);
}

public Set<Tag> getTagsForThread(ItemThread t) {
return threadsAndTags.getTagsFor(t);
}

public Set<ItemThread> getThreadsWithTag(Tag t) {
return threadsAndTags.getThreadsFor(t);
}

/**
* Gets an unmodifiable view of the Set of all {@link ItemThread}s.
*
* @return
*/
public Set<ItemThread> getThreadsUnmodifiable() {
return threadsAndTags.getAllItemThreads();
}

/**
* Gets an unmodifiable view of the Set of all {@link Tag}s.
*
* @return
*/
public Set<Tag> getTagsUnmodifiable() {
return threadsAndTags.getAllTags();
}

/**
* Object deserialization entry point.
*
* @param in
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
// Read the fields from the stream
ObjectInputStream.GetField serializedFields = in.readFields();

// Check for revision number. If no revision number, assume 1
ObjectStreamField revisionField = serializedFields.getObjectStreamClass().getField("classSerializationVersion");
byte serialVersionNumber = revisionField == null ? 1 : serializedFields.get("classSerializationVersion", (byte) 0);
//NOTE: 1 -> field does not exist (i.e. version 1), 0 -> default value

// Take the appropriate action based on revision number
switch (serialVersionNumber) {
case 1:
migrateFromVer1(serializedFields);
break;
case 2:
migrateFromVer2(serializedFields);
break;
default:
throw new UnsupportedOperationException("Version number " + serialVersionNumber + " is not supported.");
}
}

/**
* Deserialize the fields from the version 1 object in the stream and use
* them to initialize a State object of the version 2.
*
* @param serializedFields
* @throws IOException
*/
private void migrateFromVer1(ObjectInputStream.GetField serializedFields) throws IOException {
// Update fields of this State from the Stream where possible
threadsAndTags = new ThreadTagMap();
nextItemNumber = serializedFields.get("nextItemNumber", 0);
nextThreadNumber = serializedFields.get("nextThreadNumber", 0);
HashSet<Tag> tags = (HashSet<Tag>) serializedFields.get("tags", null);
HashSet<ItemThread> threads = (HashSet<ItemThread>) serializedFields.get("threads", null);

// Capture the old Tag set from the stream and add to ThreadTagMap
for (Tag tag : tags) {
threadsAndTags.addNewTag(tag);
}

// Capture the old ItemThread set and Tag mapping from the stream and add to ThreadTagMap
for (ItemThread thread : threads) {
threadsAndTags.addNewThread(thread);
for (Tag tag : thread.getTagsForClassSerializationRevision0()) {
threadsAndTags.addTagToThread(thread, tag);
}
}

//Update the revision number so the serialized version of this will
// reflect that it has been migrated to revision 2.
classSerializationVersion = 2;
}

/**
* Deserialize the fields from the version 1 object in the stream and use
* them to initialize a State object of version 2.
*
* @param serializedFields
* @throws IOException
*/
private void migrateFromVer2(ObjectInputStream.GetField serializedFields) throws IOException {
nextItemNumber = serializedFields.get("nextItemNumber", 0);
nextThreadNumber = serializedFields.get("nextThreadNumber", 0);
threadsAndTags = (ThreadTagMap) serializedFields.get("threadsAndTags", new ThreadTagMap());
classSerializationVersion = 2; //set the serialization version to 2
}
}
Loading

0 comments on commit 4b8c183

Please sign in to comment.