/**
* 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.pages;
import com.francetelecom.clara.cloud.commons.BusinessException;
import com.francetelecom.clara.cloud.commons.InvalidMavenReferenceException;
import com.francetelecom.clara.cloud.commons.MavenReference;
import com.francetelecom.clara.cloud.core.service.exception.ObjectNotFoundException;
import com.francetelecom.clara.cloud.coremodel.ApplicationRelease;
import com.francetelecom.clara.cloud.logicalmodel.*;
import com.francetelecom.clara.cloud.presentation.HomePage;
import com.francetelecom.clara.cloud.presentation.applications.SelectedAppPage;
import com.francetelecom.clara.cloud.presentation.common.Breadcrumbs;
import com.francetelecom.clara.cloud.presentation.common.NavigationMenuFirstLevel;
import com.francetelecom.clara.cloud.presentation.common.WicketUtils;
import com.francetelecom.clara.cloud.presentation.designer.panels.*;
import com.francetelecom.clara.cloud.presentation.designer.support.LogicalServicesHelper;
import com.francetelecom.clara.cloud.presentation.releases.ReleasesPage;
import com.francetelecom.clara.cloud.presentation.releases.SelectedReleasePage;
import com.francetelecom.clara.cloud.presentation.tools.BreadcrumbsItem;
import com.francetelecom.clara.cloud.presentation.tools.BusinessExceptionHandler;
import org.apache.wicket.ajax.AjaxRequestHandler;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.LoggerFactory;
import org.wicketstuff.annotation.mount.MountPath;
import java.util.ArrayList;
import java.util.List;
@MountPath("/architecture/appUid/${appUid}/releaseUid/${releaseUid}")
@AuthorizeInstantiation({"ROLE_USER","ROLE_ADMIN"})
public class DesignerPage extends DesignerHelperPage {
private static final long serialVersionUID = -807251722277505006L;
/**
* logger
*/
private static final transient org.slf4j.Logger logger = LoggerFactory.getLogger(DesignerPage.class);
@SpringBean
private LogicalServicesHelper logicalServicesHelper;
/**
* Global page feedback panel
*/
FeedbackPanel feedback;
/**
* Selected Application Release
*/
ApplicationRelease appRelease;
private DesignerSteppedProcessPanel steppedProcess;
private WebMarkupContainer firstPartContainer;
private WebMarkupContainer lockIconContainer;
private DesignerSteppedButtonsPanel stepButtonsPanel;
private DesignerArchitectureMatrixPanel matrixPanel;
private DesignerServiceDefinitionPanel serviceDefinitionPanel;
private int stepProcess;
/**
* PageTemplate constructor
*
* @param params - page parameters map
*/
public DesignerPage(PageParameters params) {
super(params);
this.stepProcess = 0;
initComponents();
}
@Override
protected void onBeforeRender() {
AjaxRequestTarget target = new AjaxRequestHandler(this);
managePageComponents(target, stepProcess, null);
super.onBeforeRender();
}
private void initComponents() {
setPageHeaderTitle("first");
setBreadcrumb();
setGlobalPageFeedback();
setFirstLevelNavigationMenu();
setProcessPipeline(stepProcess);
initLockImg();
initFirstPartContainer();
initArchitectureMatrix();
initStepButtons();
}
private void setPageHeaderTitle(String step) {
add(new Label("head_page_title",
WicketUtils.getStringResourceModel(this, "portal.design.web.title.release.architecture",
new Model<String[]>(new String[]{step}))));
}
private void setGlobalPageFeedback() {
feedback = new FeedbackPanel("feedback");
feedback.setOutputMarkupId(true);
add(feedback);
}
private void setFirstLevelNavigationMenu() {
NavigationMenuFirstLevel navFirstLvl = new NavigationMenuFirstLevel();
add(navFirstLvl);
}
/**
* Set the architecture step one breadcrumb
*/
private void setBreadcrumb() {
PageParameters params = getPageParameters();
String releaseUid = params.get("releaseUid").toString();
List<BreadcrumbsItem> breadcrumbsItems = new ArrayList<BreadcrumbsItem>();
breadcrumbsItems.add(new BreadcrumbsItem(HomePage.class, "portal.design.breadcrumbs.homepage", null,false));
try {
logger.debug("init breadcrumb for release={}", releaseUid);
appRelease = manageApplicationRelease.findApplicationReleaseByUID(releaseUid);
breadcrumbsItems.add(
new BreadcrumbsItem(
SelectedAppPage.class,
params,
"portal.design.breadcrumbs.application.home",
appRelease.getApplication().getLabel(),
false
));
breadcrumbsItems.add(
new BreadcrumbsItem(
SelectedReleasePage.class,
params,
"portal.design.breadcrumbs.release.home",
appRelease.getReleaseVersion(),
false
)
);
breadcrumbsItems.add(
new BreadcrumbsItem(
this.getClass(),
params,
"portal.design.breadcrumbs.release.architecture",
null,
true
)
);
} catch (ObjectNotFoundException e) {
String errMsg = getString("portal.release.objectnotfound");
logger.error("{} releaseUid={}", errMsg, releaseUid);
error(errMsg);
breadcrumbsItems.add(
new BreadcrumbsItem(
ReleasesPage.class,
"portal.design.breadcrumbs.release.home",
getString("portal.design.breadcrumbs.release.unknown"),
true
)
);
}
Breadcrumbs breadcrumbs = new Breadcrumbs("breadcrumbs", breadcrumbsItems);
add(breadcrumbs);
}
/**
* set the process pipeline
*/
private void setProcessPipeline(int processStep) {
steppedProcess = new DesignerSteppedProcessPanel("process", processStep);
add(steppedProcess);
steppedProcess.setOutputMarkupId(true);
}
/**
* initialize lock icon container which will contains lock icon png
* This icon will be visible if architecture is in validated state
*/
private void initLockImg() {
lockIconContainer = new WebMarkupContainer("lockImg") {
private static final long serialVersionUID = -122889791302680834L;
@Override
public boolean isVisible() {
return isArchitectureLocked();
}
};
lockIconContainer.setOutputMarkupPlaceholderTag(true);
add(lockIconContainer);
}
/**
* initialize web container which will contains
* - service selection component
* - service definition form
* - architecture validation result
* - config service validation result
*/
private void initFirstPartContainer() {
firstPartContainer = new WebMarkupContainer("firstPartContainer");
firstPartContainer.setOutputMarkupId(true);
add(firstPartContainer);
}
/**
* initialize component which content button to go to next or previous step
* of the process pipeline
*/
private void initStepButtons() {
stepButtonsPanel = new DesignerSteppedButtonsPanel("stepButtonsPanel", this, isArchitectureLocked());
add(stepButtonsPanel);
}
/**
* initialize the architecture matrix
*/
private void initArchitectureMatrix() {
Label summaryMatrixLabel = new Label("matrixPanelLabel", new Model<String>(getString("portal.design.service.configure.title")));
add(summaryMatrixLabel);
matrixPanel = new DesignerArchitectureMatrixPanel("matrix", this, isArchitectureLocked(), false);
add(matrixPanel);
}
public void managePageComponents(AjaxRequestTarget target, int step, LogicalModelItem logicalService) {
if (isArchitectureLocked()) {
step = 2;
}
updateProcessPipelinePanel(target, step);
updateFirstPartContainer(target, step, logicalService);
updateProcessButtonPanel(target, step);
updateMatrixPanel(target);
}
private void updateProcessPipelinePanel(AjaxRequestTarget target, int step) {
steppedProcess.setCurrentStep(step);
target.add(steppedProcess);
}
private void updateFirstPartContainer(AjaxRequestTarget target, int step, LogicalModelItem service) {
if (step == 2) {
PageParameters params = getPageParameters();
EmptyPanel emptyPanel1 = new EmptyPanel("serviceDefinitionPanel");
firstPartContainer.addOrReplace(emptyPanel1);
DesignerArchitectureSummaryPanel summaryPanel = new DesignerArchitectureSummaryPanel("architectureSummaryPanel", params, isArchitectureLocked(), checkLogicalDeploymentOverallConsistency(), hasWritePermission());
firstPartContainer.addOrReplace(summaryPanel);
DesignerArchitectureConfigSetPanel configSummaryPanel = new DesignerArchitectureConfigSetPanel("configServiceSummaryPanel", this, params);
firstPartContainer.addOrReplace(configSummaryPanel);
} else {
CompoundPropertyModel<List<LogicalModelItem>> compoundPropertyModel;
if (step == 0) {
compoundPropertyModel = new CompoundPropertyModel<>(logicalServicesHelper.getExternalServices());
} else {
compoundPropertyModel = new CompoundPropertyModel<>(logicalServicesHelper.getInternalServices());
}
serviceDefinitionPanel = new DesignerServiceDefinitionPanel("serviceDefinitionPanel", compoundPropertyModel, isArchitectureLocked(), step, this);
firstPartContainer.addOrReplace(serviceDefinitionPanel);
updateServiceDefinitionPanel(target, service, false);
EmptyPanel emptyPanel2 = new EmptyPanel("architectureSummaryPanel");
firstPartContainer.addOrReplace(emptyPanel2);
EmptyPanel emptyPanel3 = new EmptyPanel("configServiceSummaryPanel");
firstPartContainer.addOrReplace(emptyPanel3);
}
target.add(feedback);
target.add(firstPartContainer);
target.add(lockIconContainer);
}
private void updateProcessButtonPanel(AjaxRequestTarget target, int step) {
stepButtonsPanel.setStep(step);
target.add(stepButtonsPanel);
}
private void updateMatrixPanel(AjaxRequestTarget target) {
matrixPanel.updateTable();
target.add(matrixPanel);
}
@Override
public FeedbackPanel getFeedbackPanel() {
return this.feedback;
}
public void updateServiceDefinitionPanel(AjaxRequestTarget target, LogicalModelItem service, boolean isNew) {
serviceDefinitionPanel.updateServiceFormPanel(target, service, this, isNew);
}
public String getServiceCatalogName(LogicalModelItem service) {
String beta = logicalServicesHelper.isLogicalServiceBeta(service) ? " " + getString("portal.designer.logical.service.version.beta"): "" ;
return getString("portal.designer.logical.service."+logicalServicesHelper.getLogicalServiceCatalogName(service)) + beta;
}
private boolean checkLogicalDeploymentOverallConsistency() {
boolean isConsistent = false;
// if architecture is locked, then checkOverallConsistencyAndUpdateLogicalDeployment has already been called and, architecture is consistent
if (isArchitectureLocked()) {
isConsistent = true;
} else {
try {
logicalDeployment = manageLogicalDeployment.checkOverallConsistencyAndUpdateLogicalDeployment(logicalDeployment);
isConsistent = true;
} catch (BusinessException e) {
BusinessExceptionHandler handler = new BusinessExceptionHandler(this);
handler.error(e);
}
}
return isConsistent;
}
private boolean isArchitectureLocked() {
try {
if (!hasWritePermission()) {
return true;
}
if (appRelease == null) {
return false;
}
if (manageApplicationRelease.findApplicationReleaseByUID(appRelease.getUID()).isLocked()) {
return true;
}
} catch (BusinessException e) {
BusinessExceptionHandler handler = new BusinessExceptionHandler(this);
handler.error(e);
}
return false;
}
private boolean hasWritePermission() {
if (appRelease == null)
return false;
return appRelease.getApplication().isEditable();
}
public void addNodeServiceAssociation(String jeeProcessingLabel, String serviceLabel, AjaxRequestTarget target) {
ProcessingNode jeeProcessing = logicalDeployment.findProcessingNode(jeeProcessingLabel);
LogicalService service = logicalDeployment.listLogicalServices(null, serviceLabel).iterator().next();
jeeProcessing.addLogicalServiceUsage(service, LogicalServiceAccessTypeEnum.NOT_APPLICABLE);
saveLogicalDeployment(logicalDeployment);
matrixPanel.updateTable();
}
public void removeNodeServiceAssociation(String jeeProcessingLabel, String serviceLabel, AjaxRequestTarget target) {
ProcessingNode jeeProcessing = logicalDeployment.findProcessingNode(jeeProcessingLabel);
LogicalService service = logicalDeployment.listLogicalServices(null, serviceLabel).iterator().next();
for (LogicalNodeServiceAssociation assoc : jeeProcessing.listLogicalServicesAssociations()) {
if (assoc.areAssociated(jeeProcessing, service)) {
jeeProcessing.removeLogicalServiceUsage(assoc);
break;
}
}
saveLogicalDeployment(logicalDeployment);
matrixPanel.updateTable();
}
/**
* Save the logical deployment
*/
public void saveLogicalDeployment(LogicalDeployment ld) {
try {
logicalDeployment = manageLogicalDeployment.updateLogicalDeployment(ld);
} catch (ObjectNotFoundException exc) {
error(getString("portal.logicaldeployment.objectnotfound"));
logger.error("Error when trying to update logical deployment : "+ld.toString());
logger.error(exc.getMessage());
} catch (InvalidMavenReferenceException exc) {
error(getString("portal.logicaldeployment.invalidmavenref"));
logger.error("Error when trying to update logical deployment : "+ld.toString());
logger.error(exc.getMessage());
}
logger.debug("after saving");
}
public void removeLogicalService(LogicalModelItem service, AjaxRequestTarget target, DesignerArchitectureMatrixPanel matrixPanel) {
try {
if (service instanceof LogicalService) {
logicalDeployment.removeLogicalService((LogicalService)service);
} else if (service instanceof ProcessingNode) {
logicalDeployment.removeProcessingNode((ProcessingNode) service);
}
saveLogicalDeployment(logicalDeployment);
} catch (BusinessException e) {
// TODO - message should be "internazionalisable" and not thrown by logicalDeployment
logger.error(e.getMessage());
matrixPanel.error(e.getMessage());
target.add(matrixPanel);
} catch (Exception e) {
logger.error(e.getMessage());
matrixPanel.error(e.getMessage());
target.add(matrixPanel);
}
managePageComponents(target, stepProcess, null);
}
public List<String> getQrsApplicationVersions(String todo, String defaultModelObjectAsString) {
try {
return manageLogicalDeployment.getQrsApplicationVersions(todo, defaultModelObjectAsString); //To change body of created methods use File | Settings | File Templates.
} catch (ObjectNotFoundException e) {
// TODO : add resource message
error("no qrs application version found");
logger.debug("unable to get qrs application : {}", e);
return null;
}
}
public List<String> getQrsApplications(String todo) {
try {
return manageLogicalDeployment.getQrsApplications(todo); //To change body of created methods use File | Settings | File Templates.
} catch (ObjectNotFoundException e) {
// TODO : add resource message
error("no qrs application found");
logger.debug("unable to get qrs application : {}", e);
return null;
}
}
public List<String> getQrsServices(String todo, String defaultModelObjectAsString, String defaultModelObjectAsString1) {
try {
return manageLogicalDeployment.getQrsServices(todo, defaultModelObjectAsString, defaultModelObjectAsString1); //To change body of created methods use File | Settings | File Templates.
} catch (ObjectNotFoundException e) {
// TODO : add resource message
error("no qrs service found");
logger.debug("unable to get qrs application : {}", e);
return null;
}
}
public List<String> getQrsServicesVersions(String todo, String defaultModelObjectAsString, String defaultModelObjectAsString1, String defaultModelObjectAsString2) {
try {
return manageLogicalDeployment.getQrsServicesVersions(todo, defaultModelObjectAsString, defaultModelObjectAsString1, defaultModelObjectAsString2); //To change body of created methods use File | Settings | File Templates.
} catch (ObjectNotFoundException e) {
// TODO : add resource message
error("no qrs service version found");
logger.debug("unable to get qrs application : {}", e);
return null;
}
}
public boolean isServiceEnable(LogicalModelItem service) {
return logicalServicesHelper.isLogicalServiceEnable(service);
}
public boolean isServiceParameterEnable(LogicalModelItem service, String name) {
boolean isEnable = true;
if (service instanceof LogicalService) {
isEnable = logicalServicesHelper.isServiceParameterEnable(service, name);
} else if (service instanceof ProcessingNode) {
isEnable = logicalServicesHelper.isServiceParameterEnable(service, name);
}
return isEnable;
}
public boolean checkServiceExistence(LogicalModelItem service) {
boolean exist = false;
if (service instanceof LogicalService) {
exist = existsServiceWithName((LogicalService)service);
} else if (service instanceof ProcessingNode) {
exist = existsExecutionNodeWithName((ProcessingNode) service);
}
return exist;
}
/**
* Searches for a service with a specific name in the LogicalDeployment (could be in the service layer)
*
* @param service searched
* @return true if the LogicalDeployment contains a service named LogicalModelItem.name
*/
private boolean existsServiceWithName(LogicalService service) {
boolean exist = false;
try {
LogicalDeployment logicalDeploymentPersisted = manageLogicalDeployment.findLogicalDeployment(logicalDeployment.getId());
// TODO : modify this when label / name will be correctly identify
for (LogicalService servicePersisted : logicalDeploymentPersisted.listLogicalServices(service.getClass())) {
if (!servicePersisted.getName().equals(service.getName()) && servicePersisted.getLabel().equals(service.getLabel())) {
exist = true;
}
}
} catch (ObjectNotFoundException e) {
exist = false;
}
return exist;
}
/**
* Searches for an execution node with a specific name in the LogicalDeployment (could be in the service layer)
*
* @param service searched
* @return true if the LogicalDeployment contains an execution node named name
*/
private boolean existsExecutionNodeWithName(ProcessingNode service) {
boolean exist = false;
try {
LogicalDeployment logicalDeploymentPersisted = manageLogicalDeployment.findLogicalDeployment(logicalDeployment.getId());
for (ProcessingNode servicePersisted : logicalDeploymentPersisted.listProcessingNodes()) {
if (!servicePersisted.getName().equals(service.getName()) && servicePersisted.getLabel().equals(service.getLabel())) {
exist = true;
}
}
} catch (ObjectNotFoundException e) {
exist = false;
}
return exist;
}
public void addOrUpdateLogicalService(Form<?> form, AjaxRequestTarget target, boolean isNew) {
LogicalModelItem service = (LogicalModelItem)form.getModelObject();
if(!checkServiceExistence(service)) {
// TODO REFACTOR.... Too bad to set maven reference extension here
if (service instanceof LogicalSoapService) {
MavenReference mavenReference = ((LogicalSoapService)service).getServiceAttachments();
mavenReference.setExtension("jar");
try{
WebMarkupContainer fullvalidationContent = (WebMarkupContainer) form.get("fullvalidationContent");
CheckBox fullvalidation = (CheckBox) fullvalidationContent.get("fullvalidation");
manageLogicalDeployment.checkLogicalSoapServiceConsistency((LogicalSoapService)service, fullvalidation.getModelObject());
} catch(BusinessException ex) {
BusinessExceptionHandler handler = new BusinessExceptionHandler(this);
handler.error(ex);
target.add(getFeedbackPanel());
}
}
if (service instanceof LogicalRelationalService && ((LogicalRelationalService)service).getInitialPopulationScript() != null) {
MavenReference sqlInitScript = ((LogicalRelationalService)service).getInitialPopulationScript();
if (sqlInitScript.getGroupId() == null && sqlInitScript.getArtifactId() == null && sqlInitScript.getVersion() == null) {
((LogicalRelationalService) service).setInitialPopulationScript(null);
} else {
if (sqlInitScript.getClassifier() == null) {
sqlInitScript.setClassifier("");
sqlInitScript.setExtension("sql");
}
sqlInitScript.setExtension("sql");
}
}
if (isNew) {
if (service instanceof LogicalService) {
logicalDeployment.addLogicalService((LogicalService)service);
} else if (service instanceof ProcessingNode) {
if (service instanceof JeeProcessing) {
((ProcessingNode)service).getSoftwareReference().setExtension("ear");
}
logicalDeployment.addExecutionNode((ProcessingNode)service);
}
}
saveLogicalDeployment(logicalDeployment);
// DesignerArchitectureMatrixPanel matrixPanel = ((DesignerArchitectureMatrixPanel) get("matrix"));
// matrixPanel.updateTable();
serviceDefinitionPanel.updateServiceFormPanel(target, null, this, true);
updateMatrixPanel(target);
// target.addComponent(matrixPanel);
} else {
form.get("label").error(getString("portal.designer.service.already.exist.error", new Model<String[]>(new String[]{((RequiredTextField) form.get("label")).getInput()})));
target.add(form);
}
}
public void cancelServiceEdit(AjaxRequestTarget target) {
serviceDefinitionPanel.updateServiceFormPanel(target, null, this, true);
// updateServiceFormPanel(target, null, this, true);
// getSelectServicesPanel().updateServiceListChoices(target);
}
public LogicalServicesHelper getLogicalServicesHelper() {
return logicalServicesHelper;
}
public int getStepProcess() {
return stepProcess;
}
public void setStepProcess(int stepProcess) {
this.stepProcess = stepProcess;
}
public int nextStepProcess() {
stepProcess++;
if(stepProcess > 2) stepProcess = 2;
return stepProcess;
}
public int previousStepProcess() {
stepProcess--;
if(stepProcess < 0) stepProcess = 0;
return stepProcess;
}
}