ItEr11S12ArquitecturaClientesItEr09S11: EntryPoints mechanism now used to keep track of browser history, AKA back button support.
This commit is contained in:
parent
5dea68fa30
commit
9633509dbb
4 changed files with 125 additions and 19 deletions
|
|
@ -16,6 +16,10 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import org.navalplanner.web.common.converters.Converter;
|
import org.navalplanner.web.common.converters.Converter;
|
||||||
import org.navalplanner.web.common.converters.IConverterFactory;
|
import org.navalplanner.web.common.converters.IConverterFactory;
|
||||||
import org.zkoss.zk.ui.Execution;
|
import org.zkoss.zk.ui.Execution;
|
||||||
|
import org.zkoss.zk.ui.Page;
|
||||||
|
import org.zkoss.zk.ui.event.BookmarkEvent;
|
||||||
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <br />
|
* <br />
|
||||||
|
|
@ -23,6 +27,9 @@ import org.zkoss.zk.ui.Execution;
|
||||||
*/
|
*/
|
||||||
public class URLHandler<T> {
|
public class URLHandler<T> {
|
||||||
|
|
||||||
|
private static final String FLAG_ATTRIBUTE = URLHandler.class.getName()
|
||||||
|
+ "_";
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(URLHandler.class);
|
private static final Log LOG = LogFactory.getLog(URLHandler.class);
|
||||||
|
|
||||||
private static class EntryPointMetadata {
|
private static class EntryPointMetadata {
|
||||||
|
|
@ -66,6 +73,9 @@ public class URLHandler<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doTransition(String methodName, Object... values) {
|
public void doTransition(String methodName, Object... values) {
|
||||||
|
if (isFlagedInThisRequest())
|
||||||
|
return;
|
||||||
|
flagAlreadyExecutedInThisRequest();
|
||||||
if (!metadata.containsKey(methodName)) {
|
if (!metadata.containsKey(methodName)) {
|
||||||
LOG.error("Method " + methodName
|
LOG.error("Method " + methodName
|
||||||
+ "doesn't represent a state(It doesn't have a "
|
+ "doesn't represent a state(It doesn't have a "
|
||||||
|
|
@ -83,15 +93,55 @@ public class URLHandler<T> {
|
||||||
stringRepresentations[i] = converterFor
|
stringRepresentations[i] = converterFor
|
||||||
.asStringUngeneric(values[i]);
|
.asStringUngeneric(values[i]);
|
||||||
}
|
}
|
||||||
StringBuilder linkValue = new StringBuilder(page);
|
String fragment = getFragment(parameterNames, stringRepresentations);
|
||||||
for (int i = 0; i < parameterNames.length; i++) {
|
String requestPath = executorRetriever.getCurrent().getDesktop()
|
||||||
linkValue.append(";").append(parameterNames[i]);
|
.getRequestPath();
|
||||||
if (stringRepresentations[i] != null)
|
if (requestPath.contains(page)) {
|
||||||
linkValue.append("=").append(stringRepresentations[i]);
|
doBookmark(fragment);
|
||||||
}
|
} else
|
||||||
|
sendRedirect(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFlagedInThisRequest() {
|
||||||
|
return getRequest().getAttribute(FLAG_ATTRIBUTE) == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flagAlreadyExecutedInThisRequest() {
|
||||||
|
getRequest().setAttribute(FLAG_ATTRIBUTE, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doBookmark(String fragment) {
|
||||||
|
executorRetriever.getCurrent().getDesktop().setBookmark(
|
||||||
|
stripHash(fragment));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stripHash(String fragment) {
|
||||||
|
if (fragment.startsWith("#"))
|
||||||
|
return fragment.substring(1);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendRedirect(String fragment) {
|
||||||
|
StringBuilder linkValue = new StringBuilder(page).append(fragment);
|
||||||
executorRetriever.getCurrent().sendRedirect(linkValue.toString());
|
executorRetriever.getCurrent().sendRedirect(linkValue.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getFragment(String[] parameterNames,
|
||||||
|
String[] stringRepresentations) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
if (parameterNames.length > 0)
|
||||||
|
result.append("#");
|
||||||
|
for (int i = 0; i < parameterNames.length; i++) {
|
||||||
|
result.append(parameterNames[i]);
|
||||||
|
if (stringRepresentations[i] != null)
|
||||||
|
result.append("=").append(stringRepresentations[i]);
|
||||||
|
if (i < parameterNames.length - 1) {
|
||||||
|
result.append(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private static void callMethod(Object target, Method superclassMethod,
|
private static void callMethod(Object target, Method superclassMethod,
|
||||||
Object[] params) {
|
Object[] params) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -105,9 +155,24 @@ public class URLHandler<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S extends T> void applyIfMatches(S controller) {
|
public <S extends T> void applyIfMatches(S controller) {
|
||||||
|
String uri = getRequest().getRequestURI();
|
||||||
|
applyIfMatches(controller, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpServletRequest getRequest() {
|
||||||
Execution current = executorRetriever.getCurrent();
|
Execution current = executorRetriever.getCurrent();
|
||||||
Map<String, String> matrixParams = MatrixParameters
|
HttpServletRequest request = (HttpServletRequest) current
|
||||||
.extract((HttpServletRequest) current.getNativeRequest());
|
.getNativeRequest();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <S extends T> void applyIfMatches(S controller, String fragment) {
|
||||||
|
if (isFlagedInThisRequest()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flagAlreadyExecutedInThisRequest();
|
||||||
|
String string = insertSemicolonIfNeeded(fragment);
|
||||||
|
Map<String, String> matrixParams = MatrixParameters.extract(string);
|
||||||
Set<String> matrixParamsNames = matrixParams.keySet();
|
Set<String> matrixParamsNames = matrixParams.keySet();
|
||||||
for (Entry<String, EntryPointMetadata> entry : metadata.entrySet()) {
|
for (Entry<String, EntryPointMetadata> entry : metadata.entrySet()) {
|
||||||
EntryPointMetadata entryPointMetadata = entry.getValue();
|
EntryPointMetadata entryPointMetadata = entry.getValue();
|
||||||
|
|
@ -124,6 +189,24 @@ public class URLHandler<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <S extends T> void registerListener(final S controller, Page page) {
|
||||||
|
page.addEventListener("onBookmarkChange", new EventListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEvent(Event event) throws Exception {
|
||||||
|
BookmarkEvent bookmarkEvent = (BookmarkEvent) event;
|
||||||
|
String bookmark = bookmarkEvent.getBookmark();
|
||||||
|
applyIfMatches(controller, bookmark);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String insertSemicolonIfNeeded(String uri) {
|
||||||
|
if (!uri.startsWith(";"))
|
||||||
|
return ";" + uri;
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
private Object[] retrieveArguments(Map<String, String> matrixParams,
|
private Object[] retrieveArguments(Map<String, String> matrixParams,
|
||||||
EntryPoint linkToStateAnnotation, Class<?>[] parameterTypes) {
|
EntryPoint linkToStateAnnotation, Class<?>[] parameterTypes) {
|
||||||
Object[] result = new Object[parameterTypes.length];
|
Object[] result = new Object[parameterTypes.length];
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,7 @@ public interface IWorkerCRUDControllerEntryPoints {
|
||||||
@EntryPoint("create")
|
@EntryPoint("create")
|
||||||
public abstract void goToCreateForm();
|
public abstract void goToCreateForm();
|
||||||
|
|
||||||
|
@EntryPoint("list")
|
||||||
|
void goToList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +57,8 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
|
|
||||||
private WorkRelationshipsController editWorkRelationship;
|
private WorkRelationshipsController editWorkRelationship;
|
||||||
|
|
||||||
|
private IWorkerCRUDControllerEntryPoints workerCRUD;
|
||||||
|
|
||||||
public WorkerCRUDController() {
|
public WorkerCRUDController() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +66,8 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
Window editWindow, Window workRelationshipsWindow,
|
Window editWindow, Window workRelationshipsWindow,
|
||||||
Window addWorkRelationshipWindow,
|
Window addWorkRelationshipWindow,
|
||||||
Window editWorkRelationshipWindow, IWorkerModel workerModel,
|
Window editWorkRelationshipWindow, IWorkerModel workerModel,
|
||||||
IMessagesForUser messages) {
|
IMessagesForUser messages,
|
||||||
|
IWorkerCRUDControllerEntryPoints workerCRUD) {
|
||||||
this.createWindow = createWindow;
|
this.createWindow = createWindow;
|
||||||
this.listWindow = listWindow;
|
this.listWindow = listWindow;
|
||||||
this.editWindow = editWindow;
|
this.editWindow = editWindow;
|
||||||
|
|
@ -73,6 +76,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
this.editWorkRelationshipWindow = editWorkRelationshipWindow;
|
this.editWorkRelationshipWindow = editWorkRelationshipWindow;
|
||||||
this.workerModel = workerModel;
|
this.workerModel = workerModel;
|
||||||
this.messages = messages;
|
this.messages = messages;
|
||||||
|
this.workerCRUD = workerCRUD;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Worker getWorker() {
|
public Worker getWorker() {
|
||||||
|
|
@ -92,7 +96,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
public void save() {
|
public void save() {
|
||||||
try {
|
try {
|
||||||
workerModel.save();
|
workerModel.save();
|
||||||
getVisibility().showOnly(listWindow);
|
goToList();
|
||||||
Util.reloadBindings(listWindow);
|
Util.reloadBindings(listWindow);
|
||||||
messages.showMessage(Level.INFO, "traballador gardado");
|
messages.showMessage(Level.INFO, "traballador gardado");
|
||||||
} catch (ValidationException e) {
|
} catch (ValidationException e) {
|
||||||
|
|
@ -103,10 +107,16 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
|
goToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void goToList() {
|
||||||
|
getBookmarker().goToList();
|
||||||
getVisibility().showOnly(listWindow);
|
getVisibility().showOnly(listWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goToEditForm(Worker worker) {
|
public void goToEditForm(Worker worker) {
|
||||||
|
getBookmarker().goToEditForm(worker);
|
||||||
workerModel.prepareEditFor(worker);
|
workerModel.prepareEditFor(worker);
|
||||||
getVisibility().showOnly(editWindow);
|
getVisibility().showOnly(editWindow);
|
||||||
Util.reloadBindings(editWindow);
|
Util.reloadBindings(editWindow);
|
||||||
|
|
@ -133,6 +143,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goToCreateForm() {
|
public void goToCreateForm() {
|
||||||
|
getBookmarker().goToCreateForm();
|
||||||
workerModel.prepareForCreate();
|
workerModel.prepareForCreate();
|
||||||
getVisibility().showOnly(createWindow);
|
getVisibility().showOnly(createWindow);
|
||||||
Util.reloadBindings(createWindow);
|
Util.reloadBindings(createWindow);
|
||||||
|
|
@ -151,7 +162,6 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
localizationsForCreationController = createLocalizationsController(
|
localizationsForCreationController = createLocalizationsController(
|
||||||
comp, "createWindow");
|
comp, "createWindow");
|
||||||
comp.setVariable("controller", this, true);
|
comp.setVariable("controller", this, true);
|
||||||
getVisibility().showOnly(listWindow);
|
|
||||||
if (messagesContainer == null)
|
if (messagesContainer == null)
|
||||||
throw new RuntimeException("messagesContainer is needed");
|
throw new RuntimeException("messagesContainer is needed");
|
||||||
messages = new MessagesForUser(messagesContainer);
|
messages = new MessagesForUser(messagesContainer);
|
||||||
|
|
@ -164,9 +174,12 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
this.workerModel, this, messages),
|
this.workerModel, this, messages),
|
||||||
editWorkRelationshipWindow);
|
editWorkRelationshipWindow);
|
||||||
|
|
||||||
URLHandler<IWorkerCRUDControllerEntryPoints> handler = URLHandlerRegistry
|
final URLHandler<IWorkerCRUDControllerEntryPoints> handler = URLHandlerRegistry
|
||||||
.getRedirectorFor(IWorkerCRUDControllerEntryPoints.class);
|
.getRedirectorFor(IWorkerCRUDControllerEntryPoints.class);
|
||||||
handler.applyIfMatches(this);
|
handler.registerListener(this, page);
|
||||||
|
getVisibility().showOnly(listWindow);
|
||||||
|
handler.registerListener(this, page);
|
||||||
|
getVisibility().showOnly(listWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupWorkRelationshipController(
|
private void setupWorkRelationshipController(
|
||||||
|
|
@ -200,4 +213,8 @@ public class WorkerCRUDController extends GenericForwardComposer implements
|
||||||
return this.addWorkRelationship;
|
return this.addWorkRelationship;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IWorkerCRUDControllerEntryPoints getBookmarker() {
|
||||||
|
return workerCRUD;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import org.junit.Test;
|
||||||
import org.navalplanner.business.resources.entities.Worker;
|
import org.navalplanner.business.resources.entities.Worker;
|
||||||
import org.navalplanner.web.common.IMessagesForUser;
|
import org.navalplanner.web.common.IMessagesForUser;
|
||||||
import org.navalplanner.web.common.Level;
|
import org.navalplanner.web.common.Level;
|
||||||
|
import org.navalplanner.web.resources.worker.IWorkerCRUDControllerEntryPoints;
|
||||||
import org.navalplanner.web.resources.worker.IWorkerModel;
|
import org.navalplanner.web.resources.worker.IWorkerModel;
|
||||||
import org.navalplanner.web.resources.worker.WorkerCRUDController;
|
import org.navalplanner.web.resources.worker.WorkerCRUDController;
|
||||||
import org.zkoss.zul.api.Window;
|
import org.zkoss.zul.api.Window;
|
||||||
|
|
@ -33,6 +34,7 @@ public class WorkerCRUDControllerTest {
|
||||||
private Window workRelationshipsWindow;
|
private Window workRelationshipsWindow;
|
||||||
private Window addWorkRelationshipWindow;
|
private Window addWorkRelationshipWindow;
|
||||||
private Window editWorkRelationshipWindow;
|
private Window editWorkRelationshipWindow;
|
||||||
|
|
||||||
private WorkerCRUDController createControllerForModel(
|
private WorkerCRUDController createControllerForModel(
|
||||||
IWorkerModel workerModel) {
|
IWorkerModel workerModel) {
|
||||||
return createControllerForModel(workerModel, null);
|
return createControllerForModel(workerModel, null);
|
||||||
|
|
@ -44,17 +46,16 @@ public class WorkerCRUDControllerTest {
|
||||||
listWindow = createNiceMock(Window.class);
|
listWindow = createNiceMock(Window.class);
|
||||||
editWindow = createNiceMock(Window.class);
|
editWindow = createNiceMock(Window.class);
|
||||||
workRelationshipsWindow = createNiceMock(Window.class);
|
workRelationshipsWindow = createNiceMock(Window.class);
|
||||||
addWorkRelationshipWindow = createNiceMock(Window.class);
|
addWorkRelationshipWindow = createNiceMock(Window.class);
|
||||||
editWorkRelationshipWindow = createNiceMock(Window.class);
|
editWorkRelationshipWindow = createNiceMock(Window.class);
|
||||||
|
|
||||||
WorkerCRUDController workerCRUDController = new WorkerCRUDController(
|
WorkerCRUDController workerCRUDController = new WorkerCRUDController(
|
||||||
createWindow, listWindow, editWindow, workRelationshipsWindow,
|
createWindow, listWindow, editWindow, workRelationshipsWindow,
|
||||||
addWorkRelationshipWindow, editWorkRelationshipWindow ,workerModel, messages);
|
addWorkRelationshipWindow, editWorkRelationshipWindow,
|
||||||
|
workerModel, messages, createNiceMock(IWorkerCRUDControllerEntryPoints.class));
|
||||||
return workerCRUDController;
|
return workerCRUDController;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSave() throws Exception {
|
public void testSave() throws Exception {
|
||||||
IWorkerModel workerModel = createMock(IWorkerModel.class);
|
IWorkerModel workerModel = createMock(IWorkerModel.class);
|
||||||
|
|
@ -81,6 +82,7 @@ public class WorkerCRUDControllerTest {
|
||||||
// verify
|
// verify
|
||||||
verify(workerModel, messagesForUser);
|
verify(workerModel, messagesForUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGoToSaveAndThenCancel() {
|
public void testGoToSaveAndThenCancel() {
|
||||||
IWorkerModel workerModel = createMock(IWorkerModel.class);
|
IWorkerModel workerModel = createMock(IWorkerModel.class);
|
||||||
|
|
@ -95,7 +97,8 @@ public class WorkerCRUDControllerTest {
|
||||||
expect(workRelationshipsWindow.setVisible(true)).andReturn(false);
|
expect(workRelationshipsWindow.setVisible(true)).andReturn(false);
|
||||||
expect(addWorkRelationshipWindow.setVisible(true)).andReturn(false);
|
expect(addWorkRelationshipWindow.setVisible(true)).andReturn(false);
|
||||||
replay(createWindow, listWindow, editWindow, workRelationshipsWindow,
|
replay(createWindow, listWindow, editWindow, workRelationshipsWindow,
|
||||||
addWorkRelationshipWindow, editWorkRelationshipWindow, workerModel);
|
addWorkRelationshipWindow, editWorkRelationshipWindow,
|
||||||
|
workerModel);
|
||||||
// actions
|
// actions
|
||||||
workerCRUDController.goToCreateForm();
|
workerCRUDController.goToCreateForm();
|
||||||
workerCRUDController.cancel();
|
workerCRUDController.cancel();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue