Index: trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterHandler.java
===================================================================
--- trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterHandler.java	(revision 8)
+++ trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterHandler.java	(revision 8)
@@ -0,0 +1,75 @@
+package de.ugoe.cs.swe.bnftools.ui.formatter;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
+import org.eclipse.ltk.core.refactoring.RefactoringCore;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.xtext.parsetree.NodeAdapter;
+import org.eclipse.xtext.parsetree.NodeUtil;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.model.XtextDocument;
+
+import de.ugoe.cs.swe.bnftools.utils.RootEObjectFinder;
+
+public class FormatterHandler extends AbstractHandler {
+
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		XtextEditor editor = (XtextEditor) PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+
+		// TODO: better error handling
+		if (!(editor.getDocument() instanceof XtextDocument)) {
+			return null;
+		}
+
+		XtextDocument doc = (XtextDocument) editor.getDocument();
+		EObject root = doc.readOnly(new RootEObjectFinder());
+		NodeAdapter rootNode = NodeUtil.getNodeAdapter(root);
+
+		FormatterProcessor processor = new FormatterProcessor(editor,
+				rootNode.getParserNode(), doc);
+
+		FormatterRefactoring refactoring = new FormatterRefactoring(processor);
+		
+		try {
+			performRefactoring(refactoring);
+		} catch (InterruptedException e1) {
+			e1.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return null;
+	}
+
+	public void performRefactoring(ProcessorBasedRefactoring ref)
+			throws Exception {
+		NullProgressMonitor nullProgressMonitor = new NullProgressMonitor();
+		RefactoringStatus status = ref.checkAllConditions(nullProgressMonitor);
+		if (status.isOK()) {
+			Change change = ref.createChange(nullProgressMonitor);
+			change.initializeValidationData(nullProgressMonitor);
+			change.setEnabled(true);
+			PerformChangeOperation operation = new PerformChangeOperation(
+					change);
+			operation.setUndoManager(RefactoringCore.getUndoManager(),
+					ref.getProcessor().getProcessorName());
+			operation.run(nullProgressMonitor);
+			change.dispose();
+		} else {
+			MessageDialog.openInformation(
+					Display.getDefault().getActiveShell(), "Custom Formatter",
+					status.getMessageMatchingSeverity(status.getSeverity()));
+		}
+	}
+
+}
Index: trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterProcessor.java
===================================================================
--- trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterProcessor.java	(revision 8)
+++ trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterProcessor.java	(revision 8)
@@ -0,0 +1,122 @@
+package de.ugoe.cs.swe.bnftools.ui.formatter;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEditGroup;
+import org.eclipse.xtext.parsetree.AbstractNode;
+import org.eclipse.xtext.parsetree.CompositeNode;
+import org.eclipse.xtext.ui.editor.XtextEditor;
+import org.eclipse.xtext.ui.editor.model.XtextDocument;
+
+import de.ugoe.cs.swe.bnftools.ebnf.Rule;
+
+public class FormatterProcessor extends RefactoringProcessor {
+	IFile file;
+	private CompositeNode rootNode;
+	private XtextDocument document;
+	
+	// ----------------------------------------------------------------------------------------------------
+
+	public FormatterProcessor(XtextEditor editor, CompositeNode root, XtextDocument doc) {
+		file = (IFile) editor.getEditorInput().getAdapter(IFile.class);
+		this.rootNode = root;
+		this.document = doc;
+	}
+	
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public Object[] getElements() {
+		return null;
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public String getIdentifier() {
+		return "Formatter Processor";
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public String getProcessorName() {
+		return "Formatter Processor";
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public boolean isApplicable() throws CoreException {
+		return (rootNode != null);
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
+			throws CoreException, OperationCanceledException {
+		
+		RefactoringStatus status = new RefactoringStatus();
+
+		if (rootNode == null)
+			status.addFatalError("Root node is null!");
+
+		return status;
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public RefactoringStatus checkFinalConditions(IProgressMonitor pm,
+			CheckConditionsContext context) throws CoreException,
+			OperationCanceledException {
+		
+		return checkInitialConditions(pm);
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public Change createChange(IProgressMonitor pm) throws CoreException,
+			OperationCanceledException {
+		CompositeChange compositeChange = new CompositeChange("Custom formatter");
+		pm.beginTask("Custom formatter", 2);
+		
+		MultiTextEdit multiEdit = new MultiTextEdit();
+		TextFileChange fileChange = new TextFileChange("Custom formatter text file change", file);
+		fileChange.setEdit(multiEdit);
+		fileChange.setTextType("bnf");
+		compositeChange.add(fileChange);
+		
+		String newText = "foobar";
+		
+		ReplaceEdit replaceEdit = new ReplaceEdit(0, document.getLength(), newText);
+		multiEdit.addChild(replaceEdit);
+		
+		return compositeChange;
+		
+	}
+
+	// ----------------------------------------------------------------------------------------------------
+
+	@Override
+	public RefactoringParticipant[] loadParticipants(RefactoringStatus status,
+			SharableParticipants sharedParticipants) throws CoreException {
+		return null;
+	}
+
+}
Index: trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterRefactoring.java
===================================================================
--- trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterRefactoring.java	(revision 8)
+++ trunk/de.ugoe.cs.swe.bnftools.ebnf.ui/src/de/ugoe/cs/swe/bnftools/ui/formatter/FormatterRefactoring.java	(revision 8)
@@ -0,0 +1,19 @@
+package de.ugoe.cs.swe.bnftools.ui.formatter;
+
+import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
+
+public class FormatterRefactoring extends ProcessorBasedRefactoring {
+
+	private RefactoringProcessor processor;
+
+	public FormatterRefactoring(RefactoringProcessor processor) {
+		super(processor);
+		this.processor = (RefactoringProcessor) processor;
+	}
+
+	public RefactoringProcessor getProcessor() {
+		return processor;
+	}
+
+}
