Skip to content

Commit

Permalink
Resource visualization.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Jun 13, 2016
1 parent 6c8413c commit 8d39c59
Show file tree
Hide file tree
Showing 15 changed files with 463 additions and 5 deletions.
Expand Up @@ -1491,6 +1491,26 @@ public Breadcrumb redirectBack() {
return breadcrumb;
}

// TODO deduplicate with redirectBack
public RestartResponseException redirectBackViaRestartResponseException() {
List<Breadcrumb> breadcrumbs = getSessionStorage().getBreadcrumbs();
if (breadcrumbs.size() < 2) {
getSessionStorage().clearBreadcrumbs();

if (WebComponentUtil.isAuthorized(AuthorizationConstants.AUTZ_UI_DASHBOARD_URL,
AuthorizationConstants.AUTZ_UI_HOME_ALL_URL)) {
return new RestartResponseException(PageDashboard.class);
} else {
return new RestartResponseException(PageSelfDashboard.class);
}
}

Breadcrumb breadcrumb = breadcrumbs.get(breadcrumbs.size() - 2);
redirectBackToBreadcrumb(breadcrumb);
return breadcrumb.getRestartResponseException();
}


public void redirectBackToBreadcrumb(Breadcrumb breadcrumb) {
Validate.notNull(breadcrumb, "Breadcrumb must not be null");

Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;

Expand Down Expand Up @@ -84,7 +85,11 @@ public void setVisible(boolean visible) {
public void redirect(Component component) {
}

private <T extends Serializable> IModel<T> wrapModel(final IModel<T> model) {
public RestartResponseException getRestartResponseException() {
throw new UnsupportedOperationException("Should be implemented in a subclass");
}

private <T extends Serializable> IModel<T> wrapModel(final IModel<T> model) {
if (model == null) {
return null;
}
Expand Down
Expand Up @@ -18,6 +18,7 @@

import org.apache.commons.lang.Validate;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
Expand Down Expand Up @@ -68,7 +69,16 @@ public void redirect(Component component) {
}
}

@Override
@Override
public RestartResponseException getRestartResponseException() {
if (parameters == null) {
return new RestartResponseException(page);
} else {
return new RestartResponseException(page, parameters);
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Expand Down
Expand Up @@ -18,6 +18,7 @@

import org.apache.commons.lang.Validate;
import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.model.IModel;

Expand Down Expand Up @@ -49,7 +50,12 @@ public void redirect(Component component) {
component.setResponsePage(page);
}

@Override
@Override
public RestartResponseException getRestartResponseException() {
return new RestartResponseException(page);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Expand Down
Expand Up @@ -38,6 +38,9 @@
<button class="btn btn-default" wicket:id="save" type="submit" value="save">
<wicket:message key="org.apache.wicket.extensions.wizard.save"/>
</button>
<button class="btn btn-default" wicket:id="visualize" type="submit" value="visualize">
<wicket:message key="ResourceWizard.visualize"/>
</button>
</span>
<span class="button-group">
<button class="btn btn-success" wicket:id="finish" type="submit" value="finish">
Expand Down
Expand Up @@ -40,6 +40,7 @@ public class WizardButtonBar extends Panel implements IDefaultButtonProvider {
private static final String ID_CANCEL = "cancel";
private static final String ID_VALIDATE = "validate";
private static final String ID_SAVE = "save";
private static final String ID_VISUALIZE = "visualize";

public WizardButtonBar(String id, final Wizard wizard) {
super(id);
Expand Down Expand Up @@ -145,6 +146,20 @@ protected void onError(AjaxRequestTarget target, Form<?> form) {
};
save.add(showInFullWizardMode);
add(save);

final AjaxSubmitButton visualize = new AjaxSubmitButton(ID_VISUALIZE) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
((PageResourceWizard) getPage()).visualize(target);
}

@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(((PageBase) getPage()).getFeedbackPanel());
}
};
visualize.setVisible(moreSteps);
add(visualize);
}

private void couldntSave() {
Expand Down
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2016 Evolveum
~
~ 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.
-->

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>
<form wicket:id="form" class="form-horizontal">
<div wicket:id="dotContainer">
<wicket:message key="PageResourceVisualization.dotMessage"/>
<ul>
<li><wicket:message key="PageResourceVisualization.dot1"/> (<a href="http://www.graphviz.org">www.graphviz.org</a>).</li>
<li><wicket:message key="PageResourceVisualization.dot2"/></li>
</ul>
<wicket:message key="PageResourceVisualization.moreInformation"/>
(<a href="http://wiki.evolveum.com/TODO"><wicket:message key="PageResourceVisualization.moreInformationLink"/></a>).
<p/>
<wicket:message key="PageResourceVisualization.errorMessage"/>
<b><div wicket:id="error" /></b>
<p/>
<wicket:message key="PageResourceVisualization.seeOnline"/>
<a href="http://webgraphviz.com"><wicket:message key="PageResourceVisualization.seeOnlineLink"/></a>.
<wicket:message key="PageResourceVisualization.copyInstruction"/>
<p/>
<textarea class="form-control input-sm" wicket:id="dot" rows="10"/>
<p/>
</div>
<div wicket:id="svg" />
<span class="button-group">
<button class="btn btn-default" wicket:id="back" type="submit" value="back">
<wicket:message key="PageBase.button.back"/>
</button>
</span>
</form>
</wicket:extend>
</body>
</html>
@@ -0,0 +1,179 @@
/*
* Copyright (c) 2010-2016 Evolveum
*
* 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 com.evolveum.midpoint.web.page.admin.resources;

import com.evolveum.midpoint.gui.api.model.NonEmptyLoadableModel;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.SystemUtil;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.application.AuthorizationAction;
import com.evolveum.midpoint.web.application.PageDescriptor;
import com.evolveum.midpoint.web.component.AjaxSubmitButton;
import com.evolveum.midpoint.web.component.form.Form;
import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour;
import com.evolveum.midpoint.web.page.admin.PageAdmin;
import com.evolveum.midpoint.web.page.admin.resources.dto.ResourceVisualizationDto;
import com.evolveum.midpoint.web.util.MidPointPageParametersEncoder;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import org.apache.commons.configuration.Configuration;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;

/**
* @author mederly
*/
@PageDescriptor(url = "/admin/resources/visualization", encoder = MidPointPageParametersEncoder.class, action = {
@AuthorizationAction(actionUri = PageAdminResources.AUTH_RESOURCE_ALL,
label = PageAdminResources.AUTH_RESOURCE_ALL_LABEL,
description = PageAdminResources.AUTH_RESOURCE_ALL_DESCRIPTION),
@AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_RESOURCE_EDIT_URL,
label = "PageResourceWizard.auth.resource.label",
description = "PageResourceWizard.auth.resource.description")})
public class PageResourceVisualization extends PageAdmin {

private static final Trace LOGGER = TraceManager.getTrace(PageResourceVisualization.class);

private static final String DOT_CONFIGURATION = "midpoint.dot";
private static final String RENDERER = "renderer";
private static final String DEFAULT_RENDERER = "dot";

private static final String ID_FORM = "form";
private static final String ID_DOT_CONTAINER = "dotContainer";
private static final String ID_DOT = "dot";
private static final String ID_ERROR = "error";
private static final String ID_SVG = "svg";
private static final String ID_BACK = "back";

private static final String OPERATION_EXPORT_DATA_MODEL = PageResourceVisualization.class.getName() + ".exportDataModel";

@NotNull private final PrismObject<ResourceType> resourceObject;
@NotNull private final NonEmptyLoadableModel<ResourceVisualizationDto> visualizationModel;

public PageResourceVisualization(@NotNull PrismObject<ResourceType> resourceObject) {
this.resourceObject = resourceObject;
this.visualizationModel = new NonEmptyLoadableModel<ResourceVisualizationDto>(false) {
@NotNull
@Override
protected ResourceVisualizationDto load() {
return loadVisualizationDto();
}
};
initLayout();
}


@Override
protected IModel<String> createPageTitleModel() {
return new AbstractReadOnlyModel<String>() {
@Override
public String getObject() {
return getString("PageResourceVisualization.title", resourceObject.getName());
}
};
}

@NotNull
private ResourceVisualizationDto loadVisualizationDto() {

Task task = createSimpleTask(OPERATION_EXPORT_DATA_MODEL);
OperationResult result = task.getResult();
String dot = null;
try {
dot = getModelDiagnosticService().exportDataModel(resourceObject.asObjectable(), task, result);
} catch (CommonException|RuntimeException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't export the data model for {}", e, ObjectTypeUtil.toShortString(resourceObject));
showResult(result);
throw redirectBackViaRestartResponseException();
}

String renderer = DEFAULT_RENDERER;
Configuration dotConfig = getMidpointConfiguration().getConfiguration(DOT_CONFIGURATION);
if (dotConfig != null) {
renderer = dotConfig.getString(RENDERER, renderer);
}

renderer += " -Tsvg";
StringBuilder output = new StringBuilder();
try {
SystemUtil.executeCommand(renderer, dot, output);
return new ResourceVisualizationDto(dot, output.toString(), null);
} catch (IOException|RuntimeException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't execute SVG renderer command: {}", e, renderer);
return new ResourceVisualizationDto(dot, null, e);
}
}

private void initLayout() {
Form form = new Form(ID_FORM);
add(form);

WebMarkupContainer dotContainer = new WebMarkupContainer(ID_DOT_CONTAINER);
dotContainer.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return visualizationModel.getObject().getSvg() == null;
}
});
form.add(dotContainer);

TextArea<String> dot = new TextArea<>(ID_DOT, new PropertyModel<String>(visualizationModel, ResourceVisualizationDto.F_DOT));
dotContainer.add(dot);

Label error = new Label(ID_ERROR, new PropertyModel<String>(visualizationModel, ResourceVisualizationDto.F_EXCEPTION_AS_STRING));
dotContainer.add(error);

Label svg = new Label(ID_SVG, new PropertyModel<String>(visualizationModel, ResourceVisualizationDto.F_SVG));
svg.setEscapeModelStrings(false);
svg.add(new VisibleEnableBehaviour() {
@Override
public boolean isVisible() {
return visualizationModel.getObject().getSvg() != null;
}
});
form.add(svg);

AjaxSubmitButton back = new AjaxSubmitButton(ID_BACK) {
@Override
public void onSubmit(AjaxRequestTarget ajaxRequestTarget, org.apache.wicket.markup.html.form.Form<?> form) {
redirectBack();
}

@Override
protected void onError(AjaxRequestTarget target, org.apache.wicket.markup.html.form.Form<?> form) {
target.add(getFeedbackPanel());
}
};
form.add(back);
}


}
Expand Up @@ -115,6 +115,11 @@ public PageResourceWizard(@NotNull PageParameters parameters) {
initLayout();
}

@Override
protected void createBreadcrumb() {
createInstanceBreadcrumb();
}

@NotNull
private NonEmptyLoadableModel<PrismObject<ResourceType>> createResourceModel(final Collection<SelectorOptions<GetOperationOptions>> options) {
return new NonEmptyLoadableModel<PrismObject<ResourceType>>(false) {
Expand Down Expand Up @@ -303,4 +308,8 @@ public void detach() {
}
};
}

public void visualize(AjaxRequestTarget target) {
setResponsePage(new PageResourceVisualization(modelFull.getObject()));
}
}

0 comments on commit 8d39c59

Please sign in to comment.