package fitnesse.revisioncontrol.wiki;
import fitnesse.ComponentFactory;
import fitnesse.revisioncontrol.*;
import fitnesse.wiki.*;
import java.io.File;
import java.util.List;
import java.util.Map;
public class RevisionControlledFileSystemPage extends FileSystemPage implements RevisionControllable {
private static final String REVISION_CONTROLLER = "RevisionController";
private RevisionController revisioner;
private static final String ERROR_LOGS_NAME = "ErrorLogs";
private static final String RECENT_CHANGES_NAME = "RecentChanges";
private static final String ADD_ON_SAVE_PROP = "RevisionController.addOnSave";
protected static boolean addOnSave = false;
public RevisionControlledFileSystemPage(final String path, final String name,
final ComponentFactory componentFactory) throws Exception {
super(path, name, null, new NullVersionsController());
this.revisioner = createRevisionController(componentFactory);
}
protected RevisionControlledFileSystemPage(final String path, final String name, final WikiPage parent,
final RevisionController revisionController) throws Exception {
super(path, name, parent, new NullVersionsController());
this.revisioner = revisionController;
}
public RevisionControlledFileSystemPage(final String path, final String name,
final RevisionController revisionController) throws Exception {
this(path, name, null, revisionController);
}
private static RevisionController createRevisionController(ComponentFactory factory) throws Exception {
RevisionController revisionController = (RevisionController) factory.createComponent(REVISION_CONTROLLER);
if (revisionController == null) {
throw new IllegalStateException("A RevisionController must be configured in the FitNesse properties");
}
addOnSave = Boolean.valueOf(factory.getProperty(ADD_ON_SAVE_PROP));
return revisionController;
}
@Override
public void doCommit(PageData data) throws Exception {
if (isTransientPage())
{
super.doCommit(data);
return;
}
// Check before save since we need to know if it a new page
boolean needToAddToRevisionControl = addOnSave && !pageExists();
super.doCommit(data);
if (needToAddToRevisionControl)
{
revisioner.add(getAbsoluteFileSystemPath());
}
else if (getState().isCheckedIn() && !hasLocalLock())
{
revisioner.lock(getAbsoluteFileSystemPath());
}
}
private boolean pageExists() {
return getContentFile().exists() && getPropertiesFile().exists();
}
@Override
public PageData makePageData() throws Exception {
PageData data = super.makePageData();
if (isDeleted(data))
data.setContent("!deletedpage");
return data;
}
private boolean isDeleted(PageData data) throws Exception {
return data.isEmpty() && revisioner != null && getState().isDeleted();
}
@Override
protected WikiPage createChildPage(String name) throws Exception {
return new RevisionControlledFileSystemPage(getFileSystemPath(), name, this, revisioner);
}
@Override
public void removeChildPage(String name) throws Exception {
RevisionControlledFileSystemPage childToBeDeleted = (RevisionControlledFileSystemPage) getChildPage(name);
if (parentAndChildAreUnderRevisionControl(childToBeDeleted)) {
revisioner.delete(childToBeDeleted.getAbsoluteFileSystemPath());
if (hasCachedSubpage(name))
children.remove(name);
} else {
super.removeChildPage(name);
}
}
private boolean parentAndChildAreUnderRevisionControl(RevisionControlledFileSystemPage childPage) {
return getState().isUnderRevisionControl() &&
childPage.getState().isUnderRevisionControl() &&
childPage.getState().isCheckedIn();
}
@Override
public List<WikiPageAction> getActions() throws Exception {
WikiPagePath localPagePath = getPageCrawler().getFullPath(this);
String localPageName = PathParser.render(localPagePath);
List<WikiPageAction> actions = super.getActions();
// addRevisionControlActions(localPageName, actions);
replaceVersionsActionWithRevisionsAction(localPageName, actions);
return actions;
}
// private void addRevisionControlActions(String localPageName, List<WikiPageAction> actions) throws Exception {
// actions.addAll(RevisionControlActionsBuilder.getRevisionControlActions(localPageName, getData()));
// }
private void replaceVersionsActionWithRevisionsAction(String localPageName, List<WikiPageAction> actions) {
WikiPageAction revisionControlAction = new WikiPageAction(localPageName, "Revisions");
int position = actions.indexOf(new WikiPageAction(localPageName, "Versions"));
if (position > 0) {
actions.remove(position);
actions.add(position, revisionControlAction);
}
else {
actions.add(revisionControlAction);
}
}
/**
* @see fitnesse.revisioncontrol.RevisionControlOperation
*/
public <R> R execute(final RevisionControlOperation<R> operation) {
return operation.execute(revisioner, getAbsoluteFileSystemPath());
}
/**
* @see fitnesse.revisioncontrol.RevisionControlOperation
*/
public <R> R execute(final RevisionControlOperation<R> operation, final Map<String, String> args) {
return operation.execute(revisioner, getAbsoluteFileSystemPath(), args);
}
public boolean isExternallyRevisionControlled() {
return revisioner.isExternalRevisionControlEnabled();
}
public State getState() {
return revisioner.getState(getAbsoluteFileSystemPath());
}
public boolean hasLocalLock() {
return revisioner.hasLocalLock(getAbsoluteFileSystemPathForContentFile());
}
public String getAbsoluteFileSystemPathForContentFile() {
return getContentFile().getAbsolutePath();
}
private File getContentFile() {
return new File(getFileSystemPath() + contentFilename);
}
public String getAbsoluteFileSystemPathForPropertiesFile() {
return getPropertiesFile().getAbsolutePath();
}
private File getPropertiesFile() {
return new File(getFileSystemPath() + propertiesFilename);
}
public void clearCachedChildren() {
children.clear();
}
private boolean isTransientPage() throws Exception
{
return getName().startsWith(ERROR_LOGS_NAME) || getName().equals(RECENT_CHANGES_NAME);
}
}