/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.gd.jpdl.properties;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.part.FileEditorInput;
import org.jbpm.gd.jpdl.Logger;
import org.jbpm.gd.jpdl.Plugin;
import org.jbpm.gd.jpdl.model.Variable;
import org.jbpm.gd.jpdl.model.VariableContainer;
import org.jbpm.gd.jpdl.taskform.Field;
import org.jbpm.gd.jpdl.taskform.FieldType;
import org.jbpm.gd.jpdl.taskform.FormGenerator;
public class TaskFormGenerationDialog extends StatusDialog {
private static final String pluginId = Plugin.getDefault().getBundle().getSymbolicName();
private static final IStatus okStatus = new Status(
Status.INFO, pluginId, 0, "Press OK to generate a form in the specified filename.", null);
private static final IStatus noFileNameStatus = new Status(
Status.ERROR, pluginId, 0, "Please specify a correct filename.", null);
String taskName;
FormToolkit toolkit;
VariableContainerConfigurationComposite fieldComposite;
VariableContainer fieldContainer;
VariableContainerConfigurationComposite buttonComposite;
VariableContainer buttonContainer;
Label fileNameLabel;
Text fileNameText;
Composite fieldArea;
Composite buttonArea;
public TaskFormGenerationDialog(Shell parentShell, String taskName) {
super(parentShell);
toolkit = new FormToolkit(parentShell.getDisplay());
fieldContainer = new VariableContainerImpl();
buttonContainer = new VariableContainerImpl();
this.taskName = taskName;
}
public boolean close() {
toolkit.dispose();
return super.close();
}
protected Point getInitialSize() {
return new Point(550, 475);
}
protected Control createDialogArea(Composite parent) {
Composite area = (Composite)super.createDialogArea(parent);
area.setLayout(new FormLayout());
fieldArea = toolkit.createComposite(area);
fieldArea.setBackground(ColorConstants.menuBackground);
fieldArea.setLayout(new FormLayout());
buttonArea = toolkit.createComposite(area);
buttonArea.setBackground(ColorConstants.menuBackground);
buttonArea.setLayout(new FormLayout());
Composite formFileArea = toolkit.createComposite(area);
formFileArea.setBackground(ColorConstants.menuBackground);
formFileArea.setLayout(new FormLayout());
fieldArea.setLayoutData(createFieldAreaLayoutData());
buttonArea.setLayoutData(createButtonAreaLayoutData());
formFileArea.setLayoutData(createFormFileAreaLayoutData());
createFieldComposite(fieldArea);
createButtonComposite(buttonArea);
createFormFileField(formFileArea);
getShell().setText("Generate Task Form");
return area;
}
protected Button createButton(Composite parent, int id, String label,
boolean defaultButton) {
return super.createButton(parent, id, label, false);
}
private FormData createFieldAreaLayoutData() {
FormData result = new FormData();
result.top = new FormAttachment(0, 10);
result.left = new FormAttachment(0, 10);
result.right = new FormAttachment(100, -10);
result.height = 175;
return result;
}
private FormData createButtonAreaLayoutData() {
FormData result = new FormData();
result.top = new FormAttachment(fieldArea, 0);
result.left = new FormAttachment(0, 10);
result.right = new FormAttachment(100, -10);
result.height = 125;
return result;
}
private FormData createFormFileAreaLayoutData() {
FormData result = new FormData();
result.top = new FormAttachment(buttonArea, 0);
result.left = new FormAttachment(0, 0);
result.right = new FormAttachment(100, 0);
result.bottom = new FormAttachment(100, 0);
return result;
}
private void createFieldComposite(Composite area) {
String[] columnTitles = new String[] {"Variable Name", "Label", "Read", "Write", "Required"};
fieldComposite = VariableContainerConfigurationComposite.create(toolkit, area, false, columnTitles);
fieldComposite.setVariableContainer(fieldContainer);
fieldComposite.setBackground(ColorConstants.menuBackground);
fieldComposite.setMessage("Define the form fields:");
fieldComposite.setVariableDefaultName("field");
}
private void createButtonComposite(Composite area) {
String[] columnTitles = new String[] {"Transition Name", "Label"};
buttonComposite = VariableContainerConfigurationComposite.create(toolkit, area, true, columnTitles);
buttonComposite.setVariableContainer(buttonContainer);
buttonComposite.setBackground(ColorConstants.menuBackground);
buttonComposite.setMessage("Define the form buttons:");
buttonComposite.setVariableDefaultName("button");
}
private void createFormFileField(Composite area) {
fileNameLabel = toolkit.createLabel(area, "File name:");
fileNameLabel.setBackground(ColorConstants.menuBackground);
createFileText(area);
fileNameLabel.setLayoutData(createFileNameLabelLayoutData());
fileNameText.setLayoutData(createFileNameTextLayoutData());
}
private FormData createFileNameLabelLayoutData() {
FormData result = new FormData();
result.left = new FormAttachment(0, 15);
result.top = new FormAttachment(0, 12);
return result;
}
private FormData createFileNameTextLayoutData() {
FormData result = new FormData();
result.top = new FormAttachment(0, 10);
result.left = new FormAttachment(fileNameLabel, 5);
result.right = new FormAttachment(100, -77);
return result;
}
private void createFileText(Composite area) {
fileNameText = toolkit.createText(area, "");
if (taskName == null || "".equals(taskName)) {
taskName = "default";
}
int i = taskName.length();
fileNameText.setText(taskName + ".xhtml");
fileNameText.setSelection(0, i);
fileNameText.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
checkFileName();
}
});
checkFileName();
}
private void checkFileName() {
String fileName = fileNameText.getText();
if (fileName == null || "".equals(fileName)) {
updateStatus(noFileNameStatus);
} else {
updateStatus(okStatus);
}
}
protected void okPressed() {
generateForm();
super.okPressed();
}
private void generateForm() {
createTaskFormFile();
updateFormsXmlFile();
refreshProcessFolder();
}
private void refreshProcessFolder() {
try {
getInputFile().getParent().refreshLocal(1, null);
} catch (CoreException e) {
Logger.logError("Problem while refreshing process folder.", e);
}
}
private boolean isEmpty(String str) {
return str == null || "".equals(str);
}
private void createTaskFormFile() {
Variable[] fieldVars = fieldContainer.getVariables();
List fields = new ArrayList();
for (int i = 0; i < fieldVars.length; i++) {
Field field = new Field();
field.setVariableName(fieldVars[i].getName());
field.setLabel(isEmpty(fieldVars[i].getMappedName()) ? fieldVars[i].getName() : fieldVars[i].getMappedName());
field.setReadOnly(!fieldVars[i].isWritable() && fieldVars[i].isReadable());
field.setFieldType(FieldType.getFieldTypes()[0]);
fields.add(field);
}
Variable[] buttonVariables = buttonContainer.getVariables();
List buttons = new ArrayList();
buttons.add(org.jbpm.gd.jpdl.taskform.Button.BUTTON_SAVE);
buttons.add(org.jbpm.gd.jpdl.taskform.Button.BUTTON_CANCEL);
for (int i = 0; i < buttonVariables.length; i++) {
String name = "name";
String label;
if (!isEmpty(buttonVariables[i].getName())) {
name = buttonVariables[i].getName();
}
if (!isEmpty(buttonVariables[i].getMappedName())) {
label = buttonVariables[i].getMappedName();
} else {
label = name;
}
buttons.add(org.jbpm.gd.jpdl.taskform.Button.createTransitionButton(name, label));
}
getFile(fileNameText.getText(), FormGenerator.getForm(fields, buttons));
}
private void updateFormsXmlFile() {
IFile file = getInputFile();
IPath path = file.getProjectRelativePath();
file = file.getProject().getFile(path.removeLastSegments(1).append("forms.xml"));
try {
if (!file.exists()) {
file.create(new ByteArrayInputStream("<forms/>".getBytes()), true, null);
}
} catch (CoreException e) {
Logger.logError("Could not create forms.xml", e);
}
Document document = getDocument(file);
addForm(document);
saveDocument(file, document);
}
private void saveDocument(IFile formFile, Document document) {
try {
StringWriter stringWriter = new StringWriter();
XMLWriter xmlWriter = new XMLWriter(stringWriter, OutputFormat.createPrettyPrint());
xmlWriter.write(document);
formFile.setContents(new ByteArrayInputStream(stringWriter.getBuffer().toString().getBytes()), true, true, null);
} catch (IOException e) {
Logger.logError("Problem writing xml document to file", e);
} catch (CoreException e) {
Logger.logError("Problem writing xml document to file", e);
}
}
private Element getElementFor(String taskName, Document document) {
List list = document.getRootElement().elements("form");
for (int i = 0; i < list.size(); i++) {
Element element = (Element)list.get(i);
String candidate = element.attributeValue("task");
if (candidate != null && candidate.equals(taskName)) {
return element;
}
}
return null;
}
private void addForm(Document document) {
Element element = getElementFor(taskName, document);
if (element == null) {
element = document.getRootElement().addElement("form");
element.addAttribute("task", taskName);
}
Attribute form = element.attribute("form");
if (form == null) {
element.addAttribute("form", fileNameText.getText());
} else {
form.setValue(fileNameText.getText());
}
}
private Document getDocument(IFile file) {
try {
return new SAXReader().read(new InputStreamReader(file.getContents()));
} catch (DocumentException e) {
Logger.logError("Problem creating DOM document from forms.xml", e);
} catch (CoreException e) {
Logger.logError("Problem getting the contents from forms.xml", e);
}
return null;
}
private IFile getInputFile() {
IEditorPart editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
return ((FileEditorInput)editorPart.getEditorInput()).getFile();
}
private IFile getFile(String name, String initialContents) {
IFile file = getInputFile();
IPath path = file.getProjectRelativePath();
file = file.getProject().getFile(path.removeLastSegments(1).append(name));
try {
if (!file.exists()) {
file.create(new ByteArrayInputStream(initialContents.getBytes()), true, null);
} else {
file.setContents(new ByteArrayInputStream(initialContents.getBytes()), true, true, null);
}
} catch (CoreException e) {
Logger.logError("Could not create " + name, e);
}
return file;
}
private class VariableContainerImpl implements VariableContainer {
ArrayList variables = new ArrayList();
public void addVariable(Variable variable) {
variables.add(variable);
}
public Variable[] getVariables() {
return (Variable[])variables.toArray(new Variable[variables.size()]);
}
public void removeVariable(Variable variable) {
variables.remove(variable);
}
}
}