package org.freeplane.plugin.remote.server.v10;
import static org.freeplane.plugin.remote.RemoteUtils.*;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.docear.messages.Messages.AddNodeRequest;
import org.docear.messages.Messages.AddNodeResponse;
import org.docear.messages.Messages.ChangeNodeRequest;
import org.docear.messages.Messages.ChangeNodeResponse;
import org.docear.messages.Messages.CloseAllOpenMapsRequest;
import org.docear.messages.Messages.CloseMapRequest;
import org.docear.messages.Messages.CloseServerRequest;
import org.docear.messages.Messages.CloseUnusedMaps;
import org.docear.messages.Messages.FetchMindmapUpdatesRequest;
import org.docear.messages.Messages.FetchMindmapUpdatesResponse;
import org.docear.messages.Messages.GetNodeRequest;
import org.docear.messages.Messages.GetNodeResponse;
import org.docear.messages.Messages.ListenToUpdateOccurrenceRequest;
import org.docear.messages.Messages.MindmapAsJsonReponse;
import org.docear.messages.Messages.MindmapAsJsonRequest;
import org.docear.messages.Messages.MindmapAsXmlRequest;
import org.docear.messages.Messages.MindmapAsXmlResponse;
import org.docear.messages.Messages.MoveNodeToRequest;
import org.docear.messages.Messages.MoveNodeToResponse;
import org.docear.messages.Messages.OpenMindMapRequest;
import org.docear.messages.Messages.OpenMindMapResponse;
import org.docear.messages.Messages.ReleaseLockRequest;
import org.docear.messages.Messages.ReleaseLockResponse;
import org.docear.messages.Messages.RemoveNodeRequest;
import org.docear.messages.Messages.RemoveNodeResponse;
import org.docear.messages.Messages.RequestLockRequest;
import org.docear.messages.Messages.RequestLockResponse;
import org.docear.messages.exceptions.LockNotFoundException;
import org.docear.messages.exceptions.MapNotFoundException;
import org.docear.messages.exceptions.NodeAlreadyLockedException;
import org.docear.messages.exceptions.NodeNotFoundException;
import org.docear.messages.exceptions.NodeNotLockedByUserException;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.map.MapWriter;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.map.mindmapmode.MMapController;
import org.freeplane.features.mapio.MapIO;
import org.freeplane.features.mapio.mindmapmode.MMapIO;
import org.freeplane.features.mode.ModeController;
import org.freeplane.n3.nanoxml.XMLException;
import org.freeplane.plugin.remote.RemoteUtils;
import org.freeplane.plugin.remote.server.InternalMessages.ReleaseTimedOutLocks;
import org.freeplane.plugin.remote.server.OpenMindmapInfo;
import org.freeplane.plugin.remote.server.RemoteController;
import org.freeplane.plugin.remote.v10.model.LockModel;
import org.freeplane.plugin.remote.v10.model.MapModel;
import org.freeplane.plugin.remote.v10.model.NodeModelDefault;
import org.freeplane.plugin.remote.v10.model.updates.AddNodeUpdate;
import org.freeplane.plugin.remote.v10.model.updates.ChangeNodeAttributeUpdate;
import org.freeplane.plugin.remote.v10.model.updates.DeleteNodeUpdate;
import org.freeplane.plugin.remote.v10.model.updates.MapUpdate;
import org.freeplane.plugin.remote.v10.model.updates.MoveNodeUpdate;
import org.slf4j.Logger;
import akka.actor.ActorRef;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Actions {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static String currentSelectedMapId = null;
/**
* returns a map as a JSON-Object
*
* @param id
* ID of map
* @param nodeCount
* soft limit of node count. When limit is reached, it only loads
* the outstanding child nodes of the current node.
* @return a map model
*/
public static MindmapAsJsonReponse getMapModelJson(MindmapAsJsonRequest request) throws MapNotFoundException {
final int nodeCount = request.getNodeCount();
final String mapId = request.getMapId();
final boolean loadAllNodes = nodeCount == -1;
logger().debug("Actions.getMapModelJson => mapId:'{}'; nodeCount:{}; loadAllNodes:{}", mapId, nodeCount, loadAllNodes);
final ModeController modeController = modeController();
logger().debug("Actions.getMapModelJson => selecting map");
selectMap(mapId);
logger().debug("Actions.getMapModelJson => retrieving freeplane map");
org.freeplane.features.map.MapModel freeplaneMap = modeController.getController().getMap();
if (freeplaneMap == null) { // when not mapMode
logger().error("Actions.getMapModelJson => Current mode not MapMode!");
throw new AssertionError("Current mode not MapMode");
}
// create the MapModel for JSON
logger().debug("Actions.getMapModelJson => creating mapmodel for JSON-convertion");
final OpenMindmapInfo info = RemoteController.getMapIdInfoMap().get(mapId);
final String mapName = info.getName();
final int revision = info.getCurrentRevision();
MapModel mm = new MapModel(freeplaneMap, mapName, revision, loadAllNodes);
if (!loadAllNodes) {
RemoteUtils.loadNodesIntoModel(mm.root, nodeCount);
}
logger().debug("Actions.getMapModelJson => creating JSON string");
String result = mm.toJsonString();
logger().debug("Actions.getMapModelJson => returning JSON string");
return new MindmapAsJsonReponse(result);
}
/**
* returns a map as a JSON-Object
*
* @param id
* ID of map
* @param nodeCount
* soft limit of node count. When limit is reached, it only loads
* the outstanding child nodes of the current node.
* @return a map model
* @throws MapNotFoundException
* @throws IOException
*/
public static MindmapAsXmlResponse getMapModelXml(final MindmapAsXmlRequest request) throws MapNotFoundException, IOException {
final String mapId = request.getMapId();
logger().debug("Actions.getMapModelXml => mapId:'{}'", mapId);
logger().debug("Actions.getMapModelXml => selecting map");
selectMap(mapId);
final ModeController modeController = modeController();
final org.freeplane.features.map.MapModel freeplaneMap = modeController.getController().getMap();
if (freeplaneMap == null) { // when not mapMode
logger().error("Actions.getMapModelXml => current mode not MapMode!");
throw new AssertionError("Current mode not MapMode");
}
logger().debug("Actions.getMapModelXml => serialising map to XML");
final StringWriter writer = new StringWriter();
modeController.getMapController().getMapWriter().writeMapAsXml(freeplaneMap, writer, MapWriter.Mode.EXPORT, true, true);
final int currentRevision = getOpenMindMapInfo(mapId).getCurrentRevision();
logger().debug("Actions.getMapModelXml => returning map as XML string");
return new MindmapAsXmlResponse(writer.toString(), currentRevision);
}
/**
* closes a map on the server
*
* @param id
* @return
*/
public static void closeMap(final CloseMapRequest request) throws MapNotFoundException {
final String mapId = request.getMapId();
logger().debug("Actions.closeMap => mapId:'{}'", request.getMapId());
// select map
logger().debug("Actions.closeMap => selecting map");
selectMap(mapId);
// close and remove map
logger().debug("Actions.closeMap => closing map");
modeController().getController().close(true);
logger().debug("Actions.closeMap => removing map info from MapIdInfoMap");
openMindmapInfoMap().remove(mapId);
}
public static OpenMindMapResponse openMindmap(final OpenMindMapRequest request) {
final String mapId = request.getMapId();
final String mapContent = request.getMindmapFileContent();
final String mapName = request.getMindmapFileName();
logger().debug("Actions.openMindmap => mapId: {}; mapName: {}; content:'{}...'", mapId, mapName, mapContent.substring(0, Math.min(mapContent.length(), 20)));
// create file
final Random ran = new Random();
final String filename = "" + System.currentTimeMillis() + ran.nextInt(100);
final String tempDirPath = System.getProperty("java.io.tmpdir");
final File file = new File(tempDirPath + "/docear/" + filename + ".mm");
logger().debug("Actions.openMindmap => temporary file '{}' was created", file.getAbsolutePath());
try {
logger().debug("Actions.openMindmap => writing mindmap content to file");
FileUtils.writeStringToFile(file, mapContent);
// put map in openMap Collection
final URL pathURL = file.toURI().toURL();
final OpenMindmapInfo info = new OpenMindmapInfo(pathURL, mapName);
openMindmapInfoMap().put(mapId, info);
logger().debug("Actions.openMindmap => mindmap was put into openMindmapInfoMap ({} => {})", mapId, info.getMapUrl());
// open map
logger().debug("Actions.openMindmap => opening mindmap...");
final MMapIO mio = (MMapIO) RemoteController.getMapIO();
mio.newMap(pathURL);
logger().debug("Actions.openMindmap => map successfully loaded and opened!");
} catch (IOException e) {
throw new AssertionError(e);
} catch (URISyntaxException e) {
throw new AssertionError(e);
} catch (XMLException e) {
throw new AssertionError(e);
} finally {
logger().debug("Actions.closeMap => removing temporary file from file system");
file.delete();
}
return new OpenMindMapResponse(true);
}
public static FetchMindmapUpdatesResponse fetchUpdatesSinceRevision(FetchMindmapUpdatesRequest request) throws MapNotFoundException {
final String mapId = request.getMapId();
final Integer sinceRevision = request.getRevisionId();
logger().debug("Actions.getUpdatesSinceRevision => mapId: {}; sinceRevision: {}", mapId, sinceRevision);
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
if (info == null) {
throw new MapNotFoundException("Map with id " + mapId + " was not found", mapId);
}
List<String> list = info.getUpdateListAsJson(sinceRevision);
return new FetchMindmapUpdatesResponse(info.getCurrentRevision(), list);
}
public static void listenIfUpdateOccurs(ListenToUpdateOccurrenceRequest request, ActorRef sender) throws MapNotFoundException {
final String mapId = request.getMapId();
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
if (info == null)
throw new MapNotFoundException("Map with id " + mapId + " was not present", mapId);
info.registerUpdateListener(sender);
}
public static void closeServer(CloseServerRequest request) {
logger().debug("Actions.closeServer => no parameters");
logger().debug("Actions.closeServer => closing open maps");
closeAllOpenMaps(new CloseAllOpenMapsRequest(request.getSource(), request.getUsername()));
logger().debug("Actions.closeServer => Starting Thread to shutdown App in 2 seconds");
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger().debug("Actions.closeServer => shutting down");
System.exit(15);
}
}).start();
}
/**
* returns a node as a JSON-Object
*
* @param id
* ID of node
* @param nodeCount
* soft limit of node count. When limit is reached, it only loads
* the outstanding child nodes of the current node.
* @return a node model
* @throws MapNotFoundException
* @throws NodeNotFoundException
* @throws IOException
* @throws JsonMappingException
* @throws JsonGenerationException
*/
public static GetNodeResponse getNode(final GetNodeRequest request) throws MapNotFoundException, NodeNotFoundException, JsonGenerationException, JsonMappingException, IOException {
final String mapId = request.getMapId();
final String nodeId = request.getNodeId();
final int nodeCount = request.getNodeCount();
final boolean loadAllNodes = nodeCount == -1;
logger().debug("Actions.getNode => mapId:'{}'; nodeId:'{}'; nodeCount:{}; loadAllNodes:{}", mapId, nodeId, nodeCount, loadAllNodes);
logger().debug("Actions.getNode => selecting map");
selectMap(mapId);
logger().debug("Actions.getNode => retrieving freeplane node");
final NodeModel freeplaneNode = getNodeFromOpenMapById(mmapController(), nodeId);
logger().debug("Actions.getNode => loading into model to convert to JSON");
final NodeModelDefault node = new NodeModelDefault(freeplaneNode, loadAllNodes);
if (!loadAllNodes) {
RemoteUtils.loadNodesIntoModel(node, request.getNodeCount());
}
logger().debug("Actions.getNode => returning node as JSON");
return new GetNodeResponse(buildJSON(node));
}
public static AddNodeResponse addNode(AddNodeRequest request) throws MapNotFoundException, NodeNotFoundException, JsonGenerationException, JsonMappingException, IOException {
final String source = request.getSource();
final String username = request.getUsername();
final String mapId = request.getMapId();
final String parentNodeId = request.getParentNodeId();
logger().debug("Actions.addNode => mapId:'{}'; parentNodeId:'{}'", mapId, parentNodeId);
logger().debug("Actions.addNode => selecting map");
selectMap(mapId);
// get parent Node
logger().debug("Actions.addNode => retrieving freeplane parent node");
final NodeModel parentNode = getNodeFromOpenMapById(mmapController(), parentNodeId);
// create new node
final NodeModel node = RemoteUtils.addNodeToOpenMap(mmapController(), parentNode);
logger().debug("Actions.addNode => returning response with new node as json");
final String nodeJson = new NodeModelDefault(node, false).toJsonString();
final AddNodeUpdate update = new AddNodeUpdate(source, username, parentNodeId, node.getID(), nodeJson);
getOpenMindMapInfo(mapId).addUpdate(update);
return new AddNodeResponse(update.toJson());
}
public static ChangeNodeResponse changeNode(final ChangeNodeRequest request) throws MapNotFoundException, NodeNotFoundException, NodeNotLockedByUserException {
final String source = request.getSource();
final String username = request.getUsername();
final String mapId = request.getMapId();
final Map<String, Object> attributeMap = request.getAttributeValueMap();
final String nodeId = request.getNodeId();
logger().debug("Actions.changeNode => mapId:'{}'; nodeId:'{}'; username: '{}'; attributes: '{}'", mapId, nodeId, username, attributeMap.toString());
logger().debug("Actions.changeNode => selecting map");
selectMap(mapId);
// get node
logger().debug("Actions.changeNode => retrieving node");
final NodeModel freeplaneNode = getNodeFromOpenMapById(mmapController(), nodeId);
// check if user has lock
if (!hasUserLockOnNode(mapId, freeplaneNode, username)) {
throw new NodeNotLockedByUserException("User has no lock on node");
}
// list to collect updates done
final List<MapUpdate> updates = new ArrayList<MapUpdate>();
for (Map.Entry<String, Object> entry : attributeMap.entrySet()) {
final String attribute = entry.getKey();
final Object valueObj = entry.getValue();
logger().debug("Actions.changeNode => {} changed to {}", attribute, valueObj);
updates.add(new ChangeNodeAttributeUpdate(source, username, nodeId, attribute, valueObj));
changeNodeAttribute(freeplaneNode, attribute, valueObj);
}
logger().debug("Actions.changeNode => refreshing lock access time");
refreshLockAccessTime(freeplaneNode);
// submit changes and create list for response
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
final List<String> updateJsons = new ArrayList<String>();
for (MapUpdate update : updates) {
info.addUpdate(update);
updateJsons.add(update.toJson());
}
return new ChangeNodeResponse(updateJsons);
}
public static MoveNodeToResponse moveNodeTo(MoveNodeToRequest request) throws NodeNotFoundException {
final String source = request.getSource();
final String username = request.getUsername();
final String mapId = request.getMapId();
final String newParentNodeId = request.getNewParentNodeId();
final String nodeId = request.getNodeToMoveId();
final Integer index = request.getNewIndex();
selectMap(mapId);
RemoteUtils.moveNodeTo(mmapController(), newParentNodeId, nodeId, index);
addUpdateForMap(mapId, new MoveNodeUpdate(source, username, newParentNodeId, nodeId, index));
return new MoveNodeToResponse(true);
}
public static RemoveNodeResponse removeNode(RemoveNodeRequest request) throws NodeNotFoundException, MapNotFoundException {
final String source = request.getSource();
final String username = request.getUsername();
final String mapId = request.getMapId();
final String nodeId = request.getNodeId();
logger().debug("Actions.removeNode => mapId:'{}'; nodeId:'{}'; username:'{}'", mapId, nodeId, username);
logger().debug("Actions.removeNode => selecting map");
selectMap(request.getMapId());
logger().debug("Actions.removeNode => retrieving node");
final MMapController mapController = (MMapController) modeController().getMapController();
final NodeModel node = getNodeFromOpenMapById(mmapController(), nodeId);
// check if any node below has a lock
if (hasAnyChildALock(node)) {
return new RemoveNodeResponse(false);
}
logger().debug("Actions.removeNode => deleting node");
mapController.deleteNode(node);
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
info.addUpdate(new DeleteNodeUpdate(source, username, nodeId));
return new RemoveNodeResponse(true);
}
private static boolean hasAnyChildALock(NodeModel freeplaneNode) {
boolean hasLock = freeplaneNode.containsExtension(LockModel.class);
// check if node itself has a lock
if (hasLock)
return true;
// check child nodes have lock
for (NodeModel node : freeplaneNode.getChildren()) {
if (hasAnyChildALock(node))
return true;
}
// else no lock
return false;
}
public static RequestLockResponse requestLock(RequestLockRequest request) throws MapNotFoundException, NodeAlreadyLockedException, NodeNotFoundException {
final String mapId = request.getMapId();
final String nodeId = request.getNodeId();
final String username = request.getUsername();
final String source = request.getSource();
logger().debug("Actions.requestLock => mapId:'{}'; nodeId:'{}'; username:'{}'", mapId, nodeId, username);
logger().debug("Actions.requestLock => selecting map");
selectMap(mapId);
logger().debug("Actions.requestLock => retrieving freeplane node");
final NodeModel node = getNodeFromOpenMapById(mmapController(), nodeId);
logger().debug("Actions.requestLock => retrieving lock model");
final LockModel lockModel = node.getExtension(LockModel.class);
if (lockModel == null) { // no lock present
logger().debug("Actions.requestLock => no lock on node, creating lock...");
final String mapUpdateJson = addLockToNode(source, username, mapId, node);
return new RequestLockResponse(true, mapUpdateJson);
} else if (username.equals(lockModel.getUsername())) { // refresh from
// locking user
refreshLockAccessTime(node);
return new RequestLockResponse(true, null);
} else { // already locked by someone else
return new RequestLockResponse(false, null);
}
}
public static ReleaseLockResponse releaseLock(ReleaseLockRequest request) throws MapNotFoundException, LockNotFoundException, NodeNotFoundException {
final String mapId = request.getMapId();
final String nodeId = request.getNodeId();
final String username = request.getUsername();
final String source = request.getSource();
logger().debug("Actions.releaseLock => mapId:'{}'; nodeId:'{}'; username: {}", mapId, nodeId, username);
logger().debug("Actions.releaseLock => selecting map");
selectMap(mapId);
logger().debug("Actions.releaseLock => retrieving node");
final NodeModel node = getNodeFromOpenMapById(mmapController(), nodeId);
logger().debug("Actions.releaseLock => retrieving lock");
final LockModel lm = node.getExtension(LockModel.class);
if (lm == null) {
// No lock available, nothing to release... just quit
logger().warn("Actions.releaseLock => no lock present");
// throw new LockNotFoundException("Lock for nodeId " +
// request.getNodeId() + " not found.");
return new ReleaseLockResponse(true, null);
}
// check if correct user
if (username.equals(lm.getUsername())) {
// release lock
logger().debug("Actions.releaseLock => releasing lock");
final String updateJson = releaseLockFromNode(source, username, mapId, node);
return new ReleaseLockResponse(true, updateJson);
} else {
return new ReleaseLockResponse(false, null);
}
}
public static void releaseTimedOutLocks(ReleaseTimedOutLocks request) throws MapNotFoundException, JsonGenerationException, JsonMappingException, IOException {
final Long millisSinceRequest = request.getMillisecondsSinceRequest();
for (Entry<String, OpenMindmapInfo> entry : openMindmapInfoMap().entrySet()) {
final String mapId = entry.getKey();
final OpenMindmapInfo info = entry.getValue();
final Set<NodeModel> lockedNodes = new HashSet<NodeModel>(info.getLockedNodes());
for (NodeModel lockedNode : lockedNodes) {
LockModel lock = lockedNode.getExtension(LockModel.class);
long timeDiff = System.currentTimeMillis() - lock.getLastAccess();
if (timeDiff > millisSinceRequest) {
releaseLockFromNode("server", "server", mapId, lockedNode);
}
}
}
}
public static void closeAllOpenMaps(CloseAllOpenMapsRequest request) {
logger().debug("Actions.closeAllOpenMaps => no parameters");
Set<String> ids = new HashSet<String>(openMindmapInfoMap().keySet());
for (String mapId : ids) {
logger().debug("Actions.closeAllOpenMaps => closing map with id '{}'", mapId);
// silent fail
try {
closeMap(new CloseMapRequest(request.getSource(), request.getUsername(), mapId));
} catch (MapNotFoundException e) {
}
}
}
public static void closeUnusedMaps(CloseUnusedMaps request) throws Exception {
final long allowedMsSinceLastAccess = request.getUnusedSinceInMs();
final String source = request.getSource();
final String username = request.getUsername();
logger().debug("Actions.closeUnusedMaps => max ms since last access:'{}'", allowedMsSinceLastAccess);
final long now = System.currentTimeMillis();
for (final String mapId : new HashSet<String>(openMindmapInfoMap().keySet())) {
final OpenMindmapInfo omi = getOpenMindMapInfo(mapId);
final long lastAccessTime = omi.getLastAccessTime();
final long sinceLastAccess = now - lastAccessTime;
final long sinceLastAccessInMinutes = sinceLastAccess / 60000;
logger().debug("Actions.closeUnusedMaps => mapId:'{}'; lastAccess:{}; sinceLastAccess:{}", mapId, lastAccessTime, sinceLastAccess);
if (sinceLastAccess > allowedMsSinceLastAccess) {
// TODO tell ZooKeeper and save to hadoop
closeMap(new CloseMapRequest(source, username, mapId));
logger().info("Actions.closeUnusedMaps => map was closed, because it havent been used for about {} minutes.", sinceLastAccessInMinutes);
}
}
}
// private static org.freeplane.features.map.NodeModel
// getNodeFromOpenMapById(final String nodeId) throws NodeNotFoundException
// {
// logger().debug("Actions.getNodeFromOpenMapById => nodeId: {}", nodeId);
// final NodeModel freeplaneNode =
// modeController().getMapController().getNodeFromID(nodeId);
//
// if (freeplaneNode == null) {
// logger().error("Actions.getNodeFromOpenMapById => requested node not found; throwing exception");
// throw new NodeNotFoundException("Node with id '" + nodeId +
// "' not found.");
// }
//
// return freeplaneNode;
// }
/**
* Select Map so getMapController() has right map.
*
* @param mapId
* Id of Map
* @throws MapNotFoundException
*/
private static void selectMap(String mapId) throws MapNotFoundException {
logger().debug("Actions.selectMap => mapId:'{}'", mapId);
// check if map is already selected
if (currentSelectedMapId == mapId) {
return;
}
if (!isMapPresent(mapId)) {
logger().error("Actions.selectMap => map not found");
throw new MapNotFoundException("Map with id " + mapId + " is not present.", mapId);
}
logger().debug("Actions.selectMap => Changing map to '{}'", mapId);
final URL pathURL = getOpenMindMapInfo(mapId).getMapUrl();
try {
final MapIO mio = RemoteController.getMapIO();
mio.newMap(pathURL);
logger().debug("Actions.selectMap => Map succesfully selected");
} catch (Exception e) {
logger().error("Actions.selectMap => Error while selecting map with id '{}'", mapId);
throw new MapNotFoundException("Could not open Map with id " + mapId, e, mapId);
}
}
/**
* refresh lastAccesTime of node lock
*
* @param node
* Node with lock
*/
private static void refreshLockAccessTime(NodeModel node) {
LockModel lm = node.getExtension(LockModel.class);
if (lm != null) {
lm.setLastAccess(System.currentTimeMillis());
}
}
private static String addLockToNode(String source, String username, String mapId, NodeModel freeplaneNode) {
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
if (freeplaneNode.getExtension(LockModel.class) == null) {
final LockModel lockModel = new LockModel(username, System.currentTimeMillis());
// add node to locked list
logger().debug("Actions.addLockToNode => adding node to locked node list");
info.addLockedNode(freeplaneNode);
// add lock
freeplaneNode.addExtension(lockModel);
final ChangeNodeAttributeUpdate update = new ChangeNodeAttributeUpdate(source, username, freeplaneNode.getID(), "locked", username);
// add change to revision list
info.addUpdate(update);
return update.toJson();
} else {
throw new AssertionError("Tried to add Lock to a Node with a Lock present");
}
}
private static String releaseLockFromNode(String source, String username, String mapId, NodeModel freeplaneNode) {
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
if (freeplaneNode.getExtension(LockModel.class) != null) {
// remove node from locked list
logger().debug("Actions.releaseLockFromNode => remove node from locked list");
info.removeLockedNode(freeplaneNode);
// remove lock
freeplaneNode.removeExtension(LockModel.class);
final ChangeNodeAttributeUpdate update = new ChangeNodeAttributeUpdate(source, username, freeplaneNode.getID(), "locked", null);
// add change to revision list
info.addUpdate(update);
return update.toJson();
} else {
throw new AssertionError("Tried to remove Lock from a Node without a Lock");
}
}
private static boolean hasUserLockOnNode(String mapId, NodeModel node, String userName) {
LockModel lm = node.getExtension(LockModel.class);
if (lm == null) { // no lock at all
return false;
} else if (userName.equals(lm.getUsername())) {
return true;
} else { // locked by someone else
return false;
}
}
private static OpenMindmapInfo getOpenMindMapInfo(String mapId) {
final Map<String, OpenMindmapInfo> map = openMindmapInfoMap();
if (!map.containsKey(mapId)) {
return null;
}
return map.get(mapId);
}
private static boolean isMapPresent(String mapId) {
return (getOpenMindMapInfo(mapId) != null);
}
private static void addUpdateForMap(String mapId, MapUpdate update) {
final OpenMindmapInfo info = getOpenMindMapInfo(mapId);
if (info == null)
throw new NullPointerException();
info.addUpdate(update);
}
private static String buildJSON(Object object) {
String result = null;
try {
result = objectMapper.writeValueAsString(object);
} catch (Exception e) {
LogUtils.severe("Error while parsing object to JSON-String!", e);
throw new AssertionError(e);
}
return result;
}
private static Map<String, OpenMindmapInfo> openMindmapInfoMap() {
return RemoteController.getMapIdInfoMap();
}
private static ModeController modeController() {
return RemoteController.getModeController();
}
private static MMapController mmapController() {
return (MMapController) modeController().getMapController();
}
private static Logger logger() {
return RemoteController.getLogger();
}
}