package org.peerbox.watchservice.states; import java.nio.file.Path; import org.hive2hive.core.exceptions.NoPeerConnectionException; import org.hive2hive.core.exceptions.NoSessionException; import org.hive2hive.processframework.exceptions.InvalidProcessStateException; import org.hive2hive.processframework.exceptions.ProcessExecutionException; import org.peerbox.app.manager.file.FileInfo; import org.peerbox.app.manager.file.IFileManager; import org.peerbox.watchservice.IAction; import org.peerbox.watchservice.IFileEventManager; import org.peerbox.watchservice.conflicthandling.ConflictHandler; import org.peerbox.watchservice.filetree.IFileTree; import org.peerbox.watchservice.filetree.composite.FileComponent; import org.peerbox.watchservice.states.listeners.LocalFileUpdateListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Files in the LocalUpdateState have been uploaded and synchronized with * the H2H network, but changed locally in the meantime. The change refers * always to the actual content of a file, and not to meta-data like timestamps, as * H2H only distinguishes between file versions if their content does not equal. * * Since folders only have one version in H2H, the LocalUpdateState is not reasonable * for folders. If a folder ends up in the LocalUpdateState for some reason and tries * to upload a new version of itself, the network will reject the request. * * @author claudio */ public class LocalUpdateState extends AbstractActionState { private final static Logger logger = LoggerFactory.getLogger(LocalUpdateState.class); public LocalUpdateState(IAction action) { super(action, StateType.LOCAL_UPDATE); } @Override public ExecutionHandle execute(IFileManager fileManager) throws NoSessionException, NoPeerConnectionException, InvalidProcessStateException, ProcessExecutionException { final Path path = action.getFile().getPath(); logger.debug("Execute LOCAL UPDATE: {}", path); handle = fileManager.update(path); if (handle != null && handle.getProcess() != null) { FileInfo file = new FileInfo(action.getFile()); handle.getProcess().attachListener(new LocalFileUpdateListener(file, action.getFileEventManager().getMessageBus())); handle.executeAsync(); } else { logger.warn("Process or handle is null."); } return new ExecutionHandle(action, handle); } @Override public AbstractActionState changeStateOnLocalCreate() { logStateTransition(getStateType(), EventType.LOCAL_CREATE, StateType.LOCAL_UPDATE); return this; } @Override public AbstractActionState changeStateOnRemoteDelete() { logStateTransition(getStateType(), EventType.REMOTE_DELETE, StateType.LOCAL_CREATE); return new LocalCreateState(action); } @Override public AbstractActionState changeStateOnRemoteMove(Path oldFilePath) { logStateTransition(getStateType(), EventType.REMOTE_MOVE, StateType.LOCAL_UPDATE); return this; } @Override public AbstractActionState changeStateOnRemoteCreate() { logStateTransition(getStateType(), EventType.REMOTE_CREATE, StateType.REMOTE_CREATE); return new RemoteCreateState(action); } @Override public AbstractActionState handleRemoteCreate() { ConflictHandler.resolveConflict(action.getFile().getPath()); action.updateTimeAndQueue(); return changeStateOnRemoteCreate(); } @Override public AbstractActionState handleRemoteDelete() { action.updateTimeAndQueue(); return changeStateOnRemoteDelete(); } @Override public AbstractActionState handleRemoteUpdate() { ConflictHandler.resolveConflict(action.getFile().getPath()); action.updateTimeAndQueue(); return changeStateOnRemoteUpdate(); } @Override public AbstractActionState handleRemoteMove(Path path) { final IFileEventManager eventManager = action.getFileEventManager(); final IFileTree fileTree = eventManager.getFileTree(); final FileComponent file = action.getFile(); eventManager.getFileComponentQueue().remove(file); Path sourcePath = file.getPath(); fileTree.deleteFile(file.getPath()); fileTree.putFile(path, file); action.updateTimeAndQueue(); return changeStateOnRemoteMove(sourcePath); } }