/**
* Copyright (C) 2015 Orange
* 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.francetelecom.clara.cloud.presentation.designer.panels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.feedback.ContainerFeedbackMessageFilter;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.slf4j.LoggerFactory;
import com.francetelecom.clara.cloud.commons.GuiClassMapping;
import com.francetelecom.clara.cloud.logicalmodel.CFJavaProcessing;
import com.francetelecom.clara.cloud.logicalmodel.JeeProcessing;
import com.francetelecom.clara.cloud.logicalmodel.LogicalDeployment;
import com.francetelecom.clara.cloud.logicalmodel.LogicalModelItem;
import com.francetelecom.clara.cloud.logicalmodel.LogicalService;
import com.francetelecom.clara.cloud.logicalmodel.LogicalSoapService;
import com.francetelecom.clara.cloud.logicalmodel.ProcessingNode;
import com.francetelecom.clara.cloud.presentation.designer.pages.DesignerHelperPage;
import com.francetelecom.clara.cloud.presentation.designer.pages.DesignerPage;
import com.francetelecom.clara.cloud.services.dto.EnvironmentDetailsDto;
/**
* Created by IntelliJ IDEA.
* User: wwnl9733
* Date: 20/10/11
* Time: 14:17
* To change this template use File | Settings | File Templates.
*/
public class DesignerArchitectureMatrixPanel extends Panel {
private static final long serialVersionUID = 1050291937613160217L;
/**
* Logger
*/
private static final transient org.slf4j.Logger logger = LoggerFactory.getLogger(DesignerArchitectureMatrixPanel.class);
/**
* List of all the execution nodes of the logical model
*/
private List<ProcessingNode> colHeaders;
/**
* List of all the logical services of the logical model
*/
private List<LogicalService> rowHeaders;
/* Container which allows the refresh of the table */
private WebMarkupContainer matrixContainer;
private ListView<List<LogicalModelItem>> matrixContent;
private FeedbackPanel matrixFeedback;
private boolean readOnly = false;
private boolean allowOverride;
private EnvironmentDetailsDto envDetailsDto;
private DesignerHelperPage parentPage;
private int step = 2;
private enum CellType {
HEADER_COL,
HEADER_ROW,
DATA,
CORNER
}
public DesignerArchitectureMatrixPanel(String id, DesignerHelperPage parentPage, boolean isArchitectureLocked, boolean allowOverride) {
super(id);
this.parentPage = parentPage;
this.readOnly = isArchitectureLocked;
this.allowOverride = allowOverride;
initLists();
updateTable();
initComponents();
}
public DesignerArchitectureMatrixPanel(String id, DesignerHelperPage parentPage, EnvironmentDetailsDto selectedEnvDto, boolean isArchitectureLocked, boolean allowOverride) {
super(id);
this.parentPage = parentPage;
this.readOnly = isArchitectureLocked;
this.allowOverride = allowOverride;
setEnvDetailsDto(selectedEnvDto);
initLists();
updateTable();
initComponents();
}
public LogicalDeployment getLogicalDeployment() {
return parentPage.getLogicalDeployment();
}
public void setEnvDetailsDto(EnvironmentDetailsDto envDetailsDto) {
this.envDetailsDto = envDetailsDto;
}
private void initLists() {
colHeaders = new ArrayList<ProcessingNode>();
rowHeaders = new ArrayList<LogicalService>();
}
public int getIndexOfService(LogicalService service) {
int index = 0;
for (LogicalService serv : rowHeaders) {
index++;
if (service.equalsShallow(serv)) {
return index;
}
}
return -1;
}
public int getIndexOfNode(ProcessingNode node) {
int index = 0;
for (ProcessingNode execNode : colHeaders) {
index++;
if (execNode.equals(node)) {
return index;
}
}
return -1;
}
/**
* Generates the list contained in the table, using headers lists, and generating other cells
*
* @return the list contained in the table
*/
private List<List<LogicalModelItem>> getImprovedList() {
List<List<LogicalModelItem>> res = new ArrayList<>();
List<LogicalModelItem> firstRow = new ArrayList<>();
/* Top left corner */
firstRow.add(null);
/* We copy that row, so that we split model (effective rows) and view (effective rows + corners) */
Collections.sort(colHeaders);
firstRow.addAll(colHeaders);
res.add(firstRow);
Collections.sort(rowHeaders);
for (LogicalService rowHeader : rowHeaders) {
List<LogicalModelItem> row = new ArrayList<>();
row.add(rowHeader);
for (int i=0; i<colHeaders.size(); i++) {
row.add(null);
}
res.add(row);
}
return res;
}
/**
* Gives the type of the cell at (indexCol, indexRow)
*
* @param indexRow index of the row
* @param indexCol index of the column
* @return the type of the cell
*/
private CellType getCellTypeAt(int indexRow, int indexCol) {
if (indexRow == 0) {
if (indexCol == 0) {
/* Top left corner */
return CellType.CORNER;
} else {
/* First row : headers */
return CellType.HEADER_COL;
}
} else if (indexCol == 0) {
/* First col : headers */
return CellType.HEADER_ROW;
} else {
/* Data */
return CellType.DATA;
}
}
public void updateTable() {
logger.debug("update table");
LogicalDeployment ld = parentPage.getLogicalDeployment();
if (ld != null) {
logger.debug("logicalDeployment : " + ld);
logger.debug("services : " + ld.listLogicalServices());
logger.debug("exec : " + ld.listProcessingNodes());
colHeaders.clear();
colHeaders.addAll(ld.listProcessingNodes());
rowHeaders.clear();
rowHeaders.addAll(ld.listLogicalServices());
Collections.sort(rowHeaders);
if(matrixContent != null) {
matrixContent.setDefaultModelObject(getImprovedList());
}
} else {
// parentPage.error(getString("portal.error.architecture.notFound"));
}
logger.debug("cols/rows :" + colHeaders + " // " + rowHeaders);
}
/**
* Manages data cells. If the cell does not exist, it creates a new one and returns it, else it returns the existing one.
*
* @param model model to give to the Panel
* @param rowHeader header of the row of the cell
* @param colHeader header of the column of the cell
* @return the correct cell, created if necessary
*/
private DesignerArchitectureMatrixCellDataPanel getPanelFor(LogicalService rowHeader, ProcessingNode colHeader) {
//String headerName = colHeader.getLabel();
//String rowName = rowHeader.getName();
/*
// @todo 2 different WebGUI services (with the same name) fix equals implementation &/or throw an exception (?)
// bug when 2 different WebGUI services (with the same name) are attached to the same node
// equals implementation seems not work
// @link http://elpaaso_shp/index.php/Discuter:Portal#Logical_model
*/
DesignerArchitectureMatrixCellDataPanel dataPanel = new DesignerArchitectureMatrixCellDataPanel("content", rowHeader, colHeader) {
private static final long serialVersionUID = 1704692833383041873L;
@Override
public void onCheck(boolean selection, AjaxRequestTarget target) {
String jeeProcessingLabel = getParentCol().getLabel();
String serviceLabel = getParentRow().getLabel();
if (selection) {
if (parentPage instanceof DesignerPage) {
((DesignerPage)parentPage).addNodeServiceAssociation(jeeProcessingLabel, serviceLabel, target);
}
} else {
if (parentPage instanceof DesignerPage) {
((DesignerPage)parentPage).removeNodeServiceAssociation(jeeProcessingLabel, serviceLabel, target);
}
}
target.add(this);
}
};
return dataPanel;
}
@Override
protected void onModelChanged() {
updateTable();
}
private void initComponents() {
matrixFeedback = new FeedbackPanel("matrixFeedback", new ContainerFeedbackMessageFilter(this));
matrixFeedback.setOutputMarkupId(true);
add(matrixFeedback);
matrixContainer = new WebMarkupContainer("matrixContainer");
/* ListView - first level */
matrixContent = new ListView<List<LogicalModelItem>>("listRows", getImprovedList()) {
private static final long serialVersionUID = -6363917228846486149L;
@Override
protected void populateItem(final ListItem<List<LogicalModelItem>> listItem) {
/* ListView - secondLevel */
listItem.add(new ListView<LogicalModelItem>("listCols", listItem.getModelObject()) {
private static final long serialVersionUID = -4827251147718587694L;
@Override
protected void populateItem(ListItem<LogicalModelItem> logicalServiceListItem) {
int rowIndex = listItem.getIndex();
int colIndex = logicalServiceListItem.getIndex();
CellType type = getCellTypeAt(rowIndex, colIndex);
final LogicalService service = rowIndex > 0 ? rowHeaders.get(rowIndex - 1) : null;
final ProcessingNode node = colIndex > 0 ? colHeaders.get(colIndex - 1) : null;
String cellBackGroundColor = "externalSrvBckGrd";
if (service != null) {
if (service.getClass().getAnnotation(GuiClassMapping.class).isExternal()) {
cellBackGroundColor = "externalSrvBckGrd";
} else {
cellBackGroundColor = "internalSrvBckGrd";
}
}
/* Population of the item depends on the type of the cell */
switch (type) {
case CORNER: /* top left corner */
logicalServiceListItem.add(new AttributeModifier("class", "cornerCell"));
logicalServiceListItem.add(new Label("content", " "));
logicalServiceListItem.setVisible(!colHeaders.isEmpty() || !rowHeaders.isEmpty());
break;
case HEADER_COL: /* first cell of the col */
DesignerArchitectureMatrixCellButtonPanel headerColCellPanel
= new DesignerArchitectureMatrixCellButtonPanel("content", logicalServiceListItem.getModel(), envDetailsDto, readOnly, allowOverride) {
private static final long serialVersionUID = 7989553592786367825L;
@Override
protected void onClickDelete(AjaxRequestTarget target) {
if (parentPage instanceof DesignerPage) {
((DesignerPage)parentPage).removeLogicalService(node, target, DesignerArchitectureMatrixPanel.this);
}
}
@Override
protected void onClickEdit(AjaxRequestTarget target) {
if (parentPage instanceof DesignerPage) {
step = ((DesignerPage) parentPage).getLogicalServicesHelper().isLogicalServiceExternal(node) ? 0 : 1;
((DesignerPage)parentPage).managePageComponents(target, step, node);
}
}
@Override
protected void onClickView(AjaxRequestTarget target) {
parentPage.openModalWindow(target, node, false);
}
@Override
protected void onClickWspInfo(AjaxRequestTarget target) {
// Can never happen on a JeeProcessing
}
@Override
protected void onClickConfigOverride(AjaxRequestTarget target) {
// Can not happen for now on a JeeProcessing
}
};
logicalServiceListItem.add(new AttributeModifier("class","hColCell"));
logicalServiceListItem.add(new AttributeAppender("class", new Model<>("logicalService"), " "));
// add default ProcessingNode icon
String className = ProcessingNode.class.getSimpleName();
if (logicalServiceListItem.getModelObject() instanceof JeeProcessing) {
className = JeeProcessing.class.getSimpleName();
} else if (logicalServiceListItem.getModelObject() instanceof CFJavaProcessing) {
className = CFJavaProcessing.class.getSimpleName();
}
logicalServiceListItem.add(new AttributeAppender("class", new Model<>("Logical" + className), " "));
// if custom icon selected, display it
if (logicalServiceListItem.getModel() != null && ((ProcessingNode) logicalServiceListItem.getModelObject()).getIconUrl() != null && !((ProcessingNode) logicalServiceListItem.getModelObject()).getIconUrl().equals("")) {
logicalServiceListItem.add(new AttributeModifier("style",new Model<>("background-image:url(\""+((ProcessingNode) logicalServiceListItem.getModelObject()).getIconUrl()+"\"); background-repeat:no-repeat; background-position:5px 5px; background-size:32px 32px;")));
}
logicalServiceListItem.add(headerColCellPanel);
break;
case HEADER_ROW: /* first cell of the row */
DesignerArchitectureMatrixCellButtonPanel headerRowCellPanel = new DesignerArchitectureMatrixCellButtonPanel("content", logicalServiceListItem.getModel(), envDetailsDto, readOnly, allowOverride) {
private static final long serialVersionUID = -6883719251719480265L;
@Override
protected void onClickDelete(AjaxRequestTarget target) {
if (parentPage instanceof DesignerPage) {
((DesignerPage)parentPage).removeLogicalService(service, target, DesignerArchitectureMatrixPanel.this);
}
}
@Override
protected void onClickEdit(AjaxRequestTarget target) {
if (parentPage instanceof DesignerPage) {
step = ((DesignerPage) parentPage).getLogicalServicesHelper().isLogicalServiceExternal(service) ? 0 : 1;
((DesignerPage)parentPage).managePageComponents(target, step, service);
}
}
@Override
protected void onClickView(AjaxRequestTarget target) {
parentPage.openModalWindow(target, service, false);
}
@Override
protected void onClickWspInfo(AjaxRequestTarget target) {
parentPage.openWspInfoPanel(target, (LogicalSoapService) service, envDetailsDto);
}
@Override
protected void onClickConfigOverride(AjaxRequestTarget target) {
parentPage.openModalWindow(target, service, true);
}
};
logicalServiceListItem.add(new AttributeModifier("class", cellBackGroundColor));
logicalServiceListItem.add(new AttributeAppender("class", new Model<>("hRowCell"), " "));
logicalServiceListItem.add(new AttributeAppender("class", new Model<>("logicalService"), " "));
logicalServiceListItem.add(new AttributeAppender("class", new Model<>(service.getClass().getSimpleName()), " "));
logicalServiceListItem.add(headerRowCellPanel);
break;
case DATA:
final DesignerArchitectureMatrixCellDataPanel dataPanel = getPanelFor(service, node);
dataPanel.setEnabled(!readOnly);
dataPanel.setOutputMarkupId(true);
logicalServiceListItem.add(new AttributeModifier("class", cellBackGroundColor));
logicalServiceListItem.add(dataPanel);
break;
default:
break;
}
}
});
}
};
matrixContent.setOutputMarkupId(true);
matrixContainer.add(matrixContent);
matrixContainer.setOutputMarkupId(true);
add(matrixContainer);
setOutputMarkupId(true);
WebMarkupContainer matrixLegendContainer = new WebMarkupContainer("matrixLegendContainer") {
private static final long serialVersionUID = 8725411660499502794L;
@Override
public boolean isVisible() {
if (parentPage == null) return false;
LogicalDeployment ld = parentPage.getLogicalDeployment();
if (ld == null) return false;
return !(ld.listProcessingNodes().isEmpty() && ld.listLogicalServices().isEmpty());
}
};
add(matrixLegendContainer);
}
}