/*
* Copyright 2011 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.formbuilder.client;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.Resource;
import org.fusesource.restygwt.client.TextCallback;
import org.jbpm.formapi.client.CommonGlobals;
import org.jbpm.formapi.client.FormBuilderException;
import org.jbpm.formapi.client.bus.ui.NotificationEvent;
import org.jbpm.formapi.client.bus.ui.NotificationEvent.Level;
import org.jbpm.formapi.client.effect.FBFormEffect;
import org.jbpm.formapi.client.menu.FBMenuItem;
import org.jbpm.formapi.client.validation.FBValidationItem;
import org.jbpm.formapi.shared.api.FormItemRepresentation;
import org.jbpm.formapi.shared.api.FormRepresentation;
import org.jbpm.formapi.shared.api.RepresentationFactory;
import org.jbpm.formapi.shared.form.FormEncodingException;
import org.jbpm.formapi.shared.form.FormEncodingFactory;
import org.jbpm.formbuilder.client.bus.ExistingTasksResponseEvent;
import org.jbpm.formbuilder.client.bus.ExistingValidationsResponseEvent;
import org.jbpm.formbuilder.client.bus.LoadServerFormResponseEvent;
import org.jbpm.formbuilder.client.bus.MenuItemAddedEvent;
import org.jbpm.formbuilder.client.bus.MenuItemAddedHandler;
import org.jbpm.formbuilder.client.bus.MenuItemFromServerEvent;
import org.jbpm.formbuilder.client.bus.MenuItemRemoveEvent;
import org.jbpm.formbuilder.client.bus.MenuItemRemoveHandler;
import org.jbpm.formbuilder.client.bus.MenuOptionAddedEvent;
import org.jbpm.formbuilder.client.bus.PreviewFormResponseEvent;
import org.jbpm.formbuilder.client.bus.ui.FormSavedEvent;
import org.jbpm.formbuilder.client.bus.ui.RepresentationFactoryPopulatedEvent;
import org.jbpm.formbuilder.client.bus.ui.TaskSelectedEvent;
import org.jbpm.formbuilder.client.bus.ui.UserIsLoggedOutEvent;
import org.jbpm.formbuilder.client.menu.items.CustomMenuItem;
import org.jbpm.formbuilder.client.messages.I18NConstants;
import org.jbpm.formbuilder.client.options.MainMenuOption;
import org.jbpm.formbuilder.shared.form.MockFormDefinitionService;
import org.jbpm.formbuilder.shared.task.TaskRef;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.xml.client.XMLParser;
public class RestyFormBuilderModel implements FormBuilderService {
private static final String DEFAULT_PACKAGE = "defaultPackage";
private final EventBus bus = CommonGlobals.getInstance().getEventBus();
private final I18NConstants i18n = FormBuilderGlobals.getInstance().getI18n();
private final XmlParseHelper helper = new XmlParseHelper();
private final MockFormDefinitionService mockFormService = new MockFormDefinitionService();
private final String contextPath;
private String packageName = DEFAULT_PACKAGE;
public RestyFormBuilderModel(String contextPath) {
this.contextPath = contextPath;
//registered to save the menu items
bus.addHandler(MenuItemAddedEvent.TYPE, new MenuItemAddedHandler() {
@Override
public void onEvent(MenuItemAddedEvent event) {
FBMenuItem item = event.getMenuItem();
saveMenuItem(event.getGroupName(), item);
if (item instanceof CustomMenuItem) {
CustomMenuItem customItem = (CustomMenuItem) item;
String formItemName = customItem.getOptionName();
FormItemRepresentation formItem = customItem.getRepresentation();
saveFormItem(formItem, formItemName);
}
}
});
//registered to delete the menu items
bus.addHandler(MenuItemRemoveEvent.TYPE, new MenuItemRemoveHandler() {
@Override
public void onEvent(MenuItemRemoveEvent event) {
FBMenuItem item = event.getMenuItem();
deleteMenuItem(event.getGroupName(), item);
if (item instanceof CustomMenuItem) {
CustomMenuItem customItem = (CustomMenuItem) item;
String formItemName = customItem.getOptionName();
FormItemRepresentation formItem = customItem.getRepresentation();
deleteFormItem(formItemName, formItem);
}
}
});
}
@Override
public void setPackageName(String packageName) {
this.packageName = packageName;
}
@Override
public void getMenuItems() {
Resource resource = new Resource(URLBuilder.getMenuItemsURL(this.contextPath));
resource.get().send(new SimpleTextCallback(i18n.CouldntFindMenuItems()) {
@Override
public void onSuccess(Method method, String response) {
if (method.getResponse().getStatusCode() == Response.SC_OK) {
Map<String, List<FBMenuItem>> menuItems = helper.readMenuMap(response);
for (String groupName : menuItems.keySet()) {
for (FBMenuItem menuItem : menuItems.get(groupName)) {
populateMockFormService(menuItem);
bus.fireEvent(new MenuItemFromServerEvent(menuItem, groupName));
}
}
} else {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntFindMenuItems404()));
}
}
});
}
public void getCurrentRoles(final FormBuilderService.RolesResponseHandler handler) {
Resource resource = new Resource(URLBuilder.getCurrentRolesURL(this.contextPath));
resource.get().send(new TextCallback() {
@Override
public void onSuccess(Method method, String response) {
if (method.getResponse().getStatusCode() == Response.SC_OK) {
List<String> roles = helper.readRoles(response);
handler.onResponse(roles);
} else {
bus.fireEvent(new UserIsLoggedOutEvent());
}
}
@Override
public void onFailure(Method method, Throwable exception) {
bus.fireEvent(new UserIsLoggedOutEvent());
}
});
}
public void logout() {
Resource resource = new Resource(URLBuilder.getLogoutURL(this.contextPath));
resource.post().send(new TextCallback() {
@Override
public void onSuccess(Method method, String response) {
Window.Location.reload();
}
@Override
public void onFailure(Method method, Throwable exception) {
Window.Location.reload();
}
});
}
@Override
public void getMenuOptions() {
Resource resource = new Resource(URLBuilder.getMenuOptionsURL(this.contextPath));
resource.get().send(new SimpleTextCallback(i18n.CouldntFindMenuOptions()) {
@Override
public void onSuccess(Method method, String response) {
List<MainMenuOption> currentOptions = helper.readMenuOptions(response);
for (MainMenuOption option : currentOptions) {
bus.fireEvent(new MenuOptionAddedEvent(option));
}
}
});
}
@Override
public void saveForm(final FormRepresentation form) {
Resource resource = new Resource(URLBuilder.saveFormURL(this.contextPath, this.packageName));
try {
String json = FormEncodingFactory.getEncoder().encode(form);
resource.post().text(json).send(new SimpleTextCallback(i18n.CouldntSaveForm()) {
@Override
public void onSuccess(Method method, String response) {
int code = method.getResponse().getStatusCode();
if (code == Response.SC_CONFLICT) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.FormAlreadyUpdated()));
} else if (code != Response.SC_CREATED) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.SaveFormUnkwnownStatus(String.valueOf(code))));
} else {
String name = helper.getFormId(response);
form.setLastModified(System.currentTimeMillis());
form.setSaved(true);
form.setName(name);
bus.fireEvent(new FormSavedEvent(form));
}
}
});
} catch (FormEncodingException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntDecodeForm(), e));
}
}
@Override
public void saveFormItem(FormItemRepresentation formItem, String formItemName) {
Resource resource = new Resource(URLBuilder.saveFormItemURL(this.contextPath, this.packageName, formItemName));
try {
String xml = helper.asXml(formItemName, formItem);
resource.post().xml(XMLParser.parse(xml)).send(new SimpleTextCallback(i18n.CouldntSaveFormItem()) {
@Override
public void onSuccess(Method method, String response) {
int code = method.getResponse().getStatusCode();
if (code == Response.SC_CONFLICT) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.FormItemAlreadyUpdated()));
} else if (code != Response.SC_CREATED) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.SaveFormItemUnknownStatus(String.valueOf(code))));
} else {
String name = helper.getFormItemId(response);
bus.fireEvent(new NotificationEvent(Level.INFO, i18n.FormItemSaved(name)));
}
}
});
} catch (FormEncodingException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntDecodeFormItem(formItemName), e));
}
}
@Override
public void deleteForm(FormRepresentation form) {
Resource resource = new Resource(URLBuilder.deleteFormURL(this.contextPath, this.packageName, form.getName()));
try {
resource.delete().send(new RequestCallback() {
@Override
public void onError(Request request, Throwable exception) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingForm(""), exception));
}
@Override
public void onResponseReceived(Request request, Response response) {
int code = response.getStatusCode();
if (code != Response.SC_ACCEPTED && code != Response.SC_NO_CONTENT && code != Response.SC_OK) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.ErrorDeletingForm(String.valueOf(code))));
} else {
bus.fireEvent(new NotificationEvent(Level.INFO, i18n.FormDeleted()));
}
}
});
} catch (RequestException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingForm(""), e));
}
}
@Override
public void deleteFile(String url) throws FormBuilderException {
Resource resource = new Resource(URLBuilder.deleteFileURL(this.contextPath, this.packageName, url));
try {
resource.delete().send(new RequestCallback() {
@Override
public void onError(Request request, Throwable exception) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingFile(""), exception));
}
@Override
public void onResponseReceived(Request request, Response response) {
int code = response.getStatusCode();
if (code != Response.SC_ACCEPTED && code != Response.SC_NO_CONTENT && code != Response.SC_OK) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.ErrorDeletingFile(String.valueOf(code))));
} else {
bus.fireEvent(new NotificationEvent(Level.INFO, i18n.FileDeleted()));
}
}
});
} catch (RequestException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingForm(""), e));
}
}
@Override
public void getFiles(List<String> types, final FilesLoadedHandler handler) {
String url = URLBuilder.getFilesURL(this.contextPath, this.packageName, types);
Resource resource = new Resource(url);
resource.get().send(new SimpleTextCallback(i18n.CouldntFindFiles("")) {
@Override
public void onSuccess(Method method, String response) {
if (method.getResponse().getStatusCode() == Response.SC_OK) {
List<String> list = helper.readFiles(response);
handler.onFilesLoaded(list);
} else {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntFindFiles(
String.valueOf(method.getResponse().getStatusCode()))));
}
}
});
}
@Override
public void deleteFormItem(String formItemName, FormItemRepresentation formItem) {
Resource resource = new Resource(URLBuilder.deleteFormItemURL(this.contextPath, this.packageName, formItemName));
try {
resource.delete().send(new RequestCallback() {
@Override
public void onError(Request request, Throwable exception) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingFormItem(""), exception));
}
@Override
public void onResponseReceived(Request request, Response response) {
int code = response.getStatusCode();
if (code != Response.SC_ACCEPTED && code != Response.SC_NO_CONTENT && code != Response.SC_OK) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.ErrorDeletingFormItem(String.valueOf(code))));
} else {
bus.fireEvent(new NotificationEvent(Level.INFO, i18n.FormItemDeleted()));
}
}
});
} catch (RequestException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingFormItem(""), e));
}
}
@Override
public void generateForm(FormRepresentation form, final String language,
Map<String, Object> inputs) {
Resource resource = new Resource(URLBuilder.generateFormURL(this.contextPath, language));
try {
String xml = helper.asXml(form, inputs);
resource.post().header(Resource.HEADER_ACCEPT, Resource.CONTENT_TYPE_TEXT).
xml(XMLParser.parse(xml)).send(new SimpleTextCallback(i18n.CouldntPreviewForm()) {
@Override
public void onSuccess(Method method, String urlResponse) {
bus.fireEvent(new PreviewFormResponseEvent(urlResponse, language));
}
});
} catch (FormEncodingException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntDecodeForm(), e));
}
}
@Override
public void saveMenuItem(String groupName, final FBMenuItem item) {
Resource resource = new Resource(URLBuilder.getMenuItemsURL(this.contextPath));
String xml = helper.asXml(groupName, item);
try {
resource.post().xml(XMLParser.parse(xml)).expect(201,409).send(new RequestCallback() {
@Override
public void onError(Request request, Throwable exception) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntGenerateMenuItem(), exception));
}
@Override
public void onResponseReceived(Request request, Response response) {
int code = response.getStatusCode();
NotificationEvent event;
if (code == Response.SC_CREATED) {
event = new NotificationEvent(Level.INFO, i18n.MenuItemSaved(item.getItemId()));
} else {
event = new NotificationEvent(Level.WARN, i18n.SaveMenuItemInvalidStatus(String.valueOf(code)));
}
bus.fireEvent(event);
}
});
} catch (RequestException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntSaveMenuItem(), e));
}
}
@Override
public void deleteMenuItem(String groupName, FBMenuItem item) {
Resource resource = new Resource(URLBuilder.getMenuItemsURL(this.contextPath));
String xml = helper.asXml(groupName, item);
try {
resource.delete().xml(XMLParser.parse(xml)).send(new RequestCallback() {
@Override
public void onError(Request request, Throwable exception) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingMenuItem(), exception));
}
@Override
public void onResponseReceived(Request request, Response response) {
int code = response.getStatusCode();
if (code != Response.SC_ACCEPTED && code != Response.SC_NO_CONTENT && code != Response.SC_OK) {
bus.fireEvent(new NotificationEvent(Level.WARN, i18n.DeleteMenuItemUnkownStatus(String.valueOf(code))));
} else {
bus.fireEvent(new NotificationEvent(Level.INFO, i18n.MenuItemDeleted()));
}
}
});
} catch (RequestException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.ErrorDeletingMenuItem(), e));
}
}
@Override
public void getExistingIoAssociations(final String filter) {
String url = URLBuilder.getIoAssociationsURL(this.contextPath, this.packageName);
Resource resource = new Resource(url);
if (filter != null && !"".equals(filter)) {
resource = resource.addQueryParam("q", filter);
}
resource.get().send(new SimpleTextCallback(i18n.CouldntReadTasks()) {
@Override
public void onSuccess(Method method, String response) {
List<TaskRef> retval = helper.readTasks(response);
bus.fireEventFromSource(new ExistingTasksResponseEvent(retval, filter), RestyFormBuilderModel.this);
}
});
}
@Override
public void selectIoAssociation(String pkgName, String processName, String taskName) {
String url = URLBuilder.getIoAssociationURL(this.contextPath, pkgName, processName, taskName);
Resource resource = new Resource(url);
resource.get().send(new SimpleTextCallback(i18n.CouldntReadSingleIO()) {
@Override
public void onSuccess(Method method, String response) {
List<TaskRef> tasks = helper.readTasks(response);
if (tasks.size() == 1) {
TaskRef singleTask = tasks.iterator().next();
bus.fireEvent(new TaskSelectedEvent(singleTask));
}
}
});
}
@Override
public void getExistingValidations() {
Resource resource = new Resource(URLBuilder.getValidationsURL(this.contextPath));
resource.get().send(new SimpleTextCallback(i18n.CouldntReadValidations()) {
@Override
public void onSuccess(Method method, String response) {
try {
List<FBValidationItem> retval = helper.readValidations(response);
bus.fireEvent(new ExistingValidationsResponseEvent(retval));
} catch (Exception e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntDecodeValidations(), e));
}
}
});
}
@Override
public void getForm(final String formName) {
String url = URLBuilder.getFormURL(this.contextPath, this.packageName, formName);
Resource resource = new Resource(url);
resource.get().send(new SimpleTextCallback(i18n.CouldntFindForm(formName)) {
@Override
public void onSuccess(Method method, String response) {
if (method.getResponse().getStatusCode() == Response.SC_OK) {
List<FormRepresentation> list = helper.readForms(response);
bus.fireEvent(new LoadServerFormResponseEvent(list.isEmpty() ? null : list.iterator().next()));
} else {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntFindForm404(formName)));
}
}
});
}
@Override
public void getForms() {
String url = URLBuilder.getFormsURL(this.contextPath, this.packageName);
Resource resource = new Resource(url);
resource.get().send(new SimpleTextCallback(i18n.CouldntFindForms()) {
@Override
public void onSuccess(Method method, String response) {
if (method.getResponse().getStatusCode() == Response.SC_OK) {
List<FormRepresentation> list = helper.readForms(response);
bus.fireEvent(new LoadServerFormResponseEvent(list));
} else {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntFindForms404()));
}
}
});
}
@Override
public void populateRepresentationFactory() {
String url = URLBuilder.getRepresentationMappingsURL(this.contextPath);
Resource resource = new Resource(url);
resource.get().send(new SimpleTextCallback(i18n.CouldntReadRepresentationMappings()) {
@Override
public void onSuccess(Method method, String response) {
Map<String, String> repMap = helper.readPropertyMap(response);
for (Map.Entry<String, String> entry : repMap.entrySet()) {
RepresentationFactory.registerItemClassName(entry.getKey(), entry.getValue());
}
bus.fireEvent(new RepresentationFactoryPopulatedEvent());
}
});
}
@Override
public void loadFormTemplate(final FormRepresentation form, String language) {
final String url = URLBuilder.loadFormTemplateURL(this.contextPath, language);
Resource resource = new Resource(url);
try {
String xml = helper.asXml(form, null);
resource.post().xml(XMLParser.parse(xml)).send(new SimpleTextCallback(i18n.CouldntExportTemplate()) {
@Override
public void onSuccess(Method method, String response) {
String fileName = helper.getFileName(response);
FormPanel auxiliarForm = new FormPanel();
auxiliarForm.setMethod(FormPanel.METHOD_GET);
auxiliarForm.setAction(url);
Hidden hidden1 = new Hidden("fileName");
hidden1.setValue(fileName);
Hidden hidden2 = new Hidden("formName");
hidden2.setValue(form.getName() == null || "".equals(form.getName()) ? "template" : form.getName());
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(hidden1);
vPanel.add(hidden2);
auxiliarForm.add(vPanel);
RootPanel.get().add(auxiliarForm);
auxiliarForm.submit();
}
});
} catch (FormEncodingException e) {
bus.fireEvent(new NotificationEvent(Level.ERROR, i18n.CouldntDecodeForm(), e));
}
}
@Override
public FormRepresentation toBasicForm(TaskRef task) {
return mockFormService.createFormFromTask(task);
}
@Override
public String getUploadFileURL() {
return URLBuilder.uploadFileURL(this.contextPath, this.packageName);
}
@Override
public String getUploadActionURL() {
return URLBuilder.uploadActionURL();
}
private void populateMockFormService(FBMenuItem item) {
String className = item.getClass().getName();
List<String> effectClassNames = new ArrayList<String>();
if (item.getFormEffects() != null) {
for (FBFormEffect effect : item.getFormEffects()) {
effectClassNames.add(effect.getClass().getName());
}
}
if (item.getAllowedEvents() != null) {
mockFormService.putActionsForItem(className, item.getAllowedEvents());
}
mockFormService.putEffectsForItem(className, effectClassNames);
}
}