/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.view.internal.internal;
import com.google.common.base.Optional;
import com.qcadoo.view.api.ComponentState;
import com.qcadoo.view.internal.api.ContainerState;
import com.qcadoo.view.internal.api.InternalComponentState;
import com.qcadoo.view.internal.api.InternalViewDefinitionState;
import com.qcadoo.view.internal.states.AbstractContainerState;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.*;
public final class ViewDefinitionStateImpl extends AbstractContainerState implements InternalViewDefinitionState {
private String redirectToUrl;
private boolean openInNewWindow;
private boolean openInModalWindow;
private boolean shouldSerializeWindow;
private final Map<String, ComponentState> registry = new HashMap<>();
private final ViewDefinitionStateLogger logger;
private boolean viewAfterReload = false;
private boolean viewAfterRedirect = false;
private JSONObject jsonContext;
public ViewDefinitionStateImpl() {
super();
requestRender();
logger = ViewDefinitionStateLogger.forView(this);
}
@Override
protected void initializeContent(final JSONObject json) throws JSONException {
// empty
}
@Override
public JSONObject render() throws JSONException {
if (redirectToUrl == null) {
return super.render();
}
JSONObject json = new JSONObject();
JSONObject jsonRedirect = new JSONObject();
json.put("redirect", jsonRedirect);
jsonRedirect.put("url", redirectToUrl);
jsonRedirect.put("openInNewWindow", openInNewWindow);
jsonRedirect.put("openInModalWindow", openInModalWindow);
jsonRedirect.put("shouldSerializeWindow", shouldSerializeWindow);
return json;
}
@Override
protected JSONObject renderContent() throws JSONException {
JSONObject json = new JSONObject();
boolean isOk = true;
List<InternalComponentState> states = getStatesAsList(getChildren().values());
for (ComponentState state : states) {
if (state.isHasError()) {
isOk = false;
break;
}
}
json.put("status", isOk ? "ok" : "error");
return json;
}
@Override
public void performEvent(final String component, final String event, final String... args) {
if (component == null) {
performEventOnChildren(getChildren().values(), event, args);
} else {
getComponentByPath(component).performEvent(this, event, args);
}
}
private ComponentState getComponentByPath(final String path) {
ComponentState componentState = this;
String[] pathParts = path.split("\\.");
for (int i = 0; i < pathParts.length; i++) {
ContainerState container = (ContainerState) componentState;
componentState = container.getChild(pathParts[i]);
if (componentState == null) {
return null;
}
}
return componentState;
}
@Override
public ComponentState getComponentByReference(final String reference) {
return registry.get(reference);
}
@Override
public <T extends ComponentState> Optional<T> tryFindComponentByReference(final String reference) {
try {
Optional<T> maybeComponent = Optional.fromNullable((T) getComponentByReference(reference));
if (!maybeComponent.isPresent()) {
logger.logDebug(String.format("Cannot find component with reference name = '%s'", reference));
}
return maybeComponent;
} catch (ClassCastException cce) {
logger.logWarn(
String.format("Component with reference name = '%s' isn't a kind of expected component type.", reference),
cce);
return Optional.absent();
}
}
private void performEventOnChildren(final Collection<InternalComponentState> components, final String event,
final String... args) {
for (ComponentState component : components) {
component.performEvent(this, event, args);
if (component instanceof ContainerState) {
performEventOnChildren(((ContainerState) component).getChildren().values(), event, args);
}
}
}
private List<InternalComponentState> getStatesAsList(final Collection<InternalComponentState> states) {
List<InternalComponentState> list = new ArrayList<>();
list.addAll(states);
for (InternalComponentState state : states) {
if (state instanceof ContainerState) {
list.addAll(getStatesAsList(((ContainerState) state).getChildren().values()));
}
}
return list;
}
@Override
public void redirectTo(final String redirectToUrl, final boolean openInNewWindow, final boolean shouldSerialize) {
this.redirectToUrl = redirectToUrl;
this.openInNewWindow = openInNewWindow;
openInModalWindow = false;
this.shouldSerializeWindow = shouldSerialize;
}
@Override
public void redirectTo(final String redirectToUrl, final boolean openInNewWindow, final boolean shouldSerialize,
final Map<String, Object> parameters) {
JSONObject context = new JSONObject(parameters);
StringBuilder url = new StringBuilder(redirectToUrl);
if (redirectToUrl.contains("?")) {
url.append("&");
} else {
url.append("?");
}
url.append("context=");
url.append(context.toString());
redirectTo(url.toString(), openInNewWindow, shouldSerialize);
}
@Override
public void openModal(final String url) {
this.redirectToUrl = url;
this.openInNewWindow = false;
openInModalWindow = true;
this.shouldSerializeWindow = true;
}
@Override
public void registerComponent(final String reference, final ComponentState state) {
if (registry.containsKey(reference)) {
throw new IllegalStateException("Duplicated state reference : " + reference);
}
registry.put(reference, state);
}
public void setViewAfterReload(boolean viewAfterReload) {
this.viewAfterReload = viewAfterReload;
}
@Override
public boolean isViewAfterReload() {
return viewAfterReload;
}
public void setViewAfterRedirect(boolean viewAfterRedirect) {
this.viewAfterRedirect = viewAfterRedirect;
}
@Override public boolean isViewAfterRedirect() {
return viewAfterRedirect;
}
@Override
public JSONObject getJsonContext() {
return jsonContext;
}
@Override
public void setJsonContext(JSONObject jsonContext) {
this.jsonContext = jsonContext;
}
}