Skip to content

Commit

Permalink
Add automatic artifact generation for bash, python artifact types. (w…
Browse files Browse the repository at this point in the history
  • Loading branch information
DominikVoigt authored Jan 12, 2023
1 parent d869db8 commit 49a4536
Show file tree
Hide file tree
Showing 26 changed files with 1,113 additions and 510 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
* Copyright (c) 2020-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -24,7 +24,7 @@ import { WineryModalModule } from '../../../wineryModalModule/winery.modal.modul
import { WineryNamespaceSelectorModule } from '../../../wineryNamespaceSelector/wineryNamespaceSelector.module';
import { WineryDuplicateValidatorModule } from '../../../wineryValidators/wineryDuplicateValidator.module';
import { WineryPipesModule } from '../../../wineryPipes/wineryPipes.module';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';
import { ArtifactsComponent } from './artifacts.component';
import { WineryQNameSelectorModule } from '../../../wineryQNameSelector/wineryQNameSelector.module';
import { ArtifactsService } from './artifacts.service';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Contributors to the Eclipse Foundation
* Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -26,7 +26,7 @@ import { WineryModalModule } from '../../../wineryModalModule/winery.modal.modul
import { WineryTableModule } from '../../../wineryTableModule/wineryTable.module';
import { ImplementationsComponent } from './implementations.component';
import { WineryPipesModule } from '../../../wineryPipes/wineryPipes.module';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';

@NgModule({
imports: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Contributors to the Eclipse Foundation
* Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -22,7 +22,7 @@ import { WineryQNameSelectorModule } from '../../../wineryQNameSelector/wineryQN
import { SelectModule } from 'ng2-select';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.moudle';
import { WineryAddModule } from '../../../wineryAddComponentModule/addComponent.module';

@NgModule({
imports: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Contributors to the Eclipse Foundation
* Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -20,9 +20,9 @@ export class GenerateArtifactApiData {
autoCreateArtifactTemplate: string;
autoGenerateIA: string;
// MUST be set
artifactType = '{http://opentosca.org/artifacttypes}WAR';
// = '{http://opentosca.org/artifacttypes}WAR';
artifactType: string;
artifactSpecificContent: string;
interfaceName: string;
operationName: string;
javaPackage: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright (c) 2017-2022 Contributors to the Eclipse Foundation
~ Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
~
~ See the NOTICE file(s) distributed with this work for additional
~ information regarding copyright ownership.
Expand Down Expand Up @@ -192,20 +192,17 @@
<winery-modal-header [title]="'Generate Implementation Artifact'"></winery-modal-header>
<winery-modal-body>
<form *ngIf="!generating; else loadingGeneration" #generateForm="ngForm">
<div class="form-group">
<label for="javaPackage" class="control-label">Java Package</label>
<input type="text" name="javaPackage" [(ngModel)]="generateArtifactApiData.javaPackage"
required id="javaPackage"
class="form-control">
</div>
<winery-component-exists [generateData]="implementation" [modalRef]="generateImplModal">
</winery-component-exists>
<p>
There is no check for the name of the implementation artifact. The artifact template name will be reused
as implementation artifact name without any further check.
</p>
<winery-component-exists [generateData]="artifactTemplate" [modalRef]="generateImplModal">
</winery-component-exists>
<div *ngIf="artifactTypes && artifactTemplate.selectedInterface">
<winery-component-exists [generateData]="artifactTemplate" [modalRef]="generateImplModal"
[artifactTypes]="artifactTypes">
</winery-component-exists>
</div>
</form>
<ng-template #loadingGeneration>
<winery-loader></winery-loader>
Expand All @@ -215,6 +212,7 @@
[closeButtonLabel]="'Cancel'"
[okButtonLabel]="'Generate'"
[disableOkButton]="!(implementation.createComponent || artifactTemplate.createComponent)"
(onOk)="generateImplementationArtifact()">
(onOk)="generateImplementationArtifact()"
(onCancel)="handleCancel()">
</winery-modal-footer>
</winery-modal>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017-2022 Contributors to the Eclipse Foundation
* Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -18,7 +18,7 @@ import { ExistService } from '../../../wineryUtils/existService';
import { WineryValidatorObject } from '../../../wineryValidators/wineryDuplicateValidator.directive';
import { InstanceService } from '../../instance.service';
import { GenerateArtifactApiData } from './generateArtifactApiData';
import { InterfacesService } from './interfaces.service';
import { IAReport, InterfacesService } from './interfaces.service';
import { InheritedInterface, InterfaceOperationApiData, InterfacesApiData } from './interfacesApiData';
import { InterfaceParameter } from '../../../model/parameters';
import { ModalDirective } from 'ngx-bootstrap';
Expand All @@ -31,6 +31,8 @@ import { WineryVersion } from '../../../model/wineryVersion';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Router } from '@angular/router';
import { Interfaces } from './interfaces';
import { ArtifactTypeSelectData } from '../../../model/selectData';
import { WineryArtifactService } from '../wineryArtifacts/artifact.service';

@Component({
selector: 'winery-instance-interfaces',
Expand Down Expand Up @@ -74,10 +76,12 @@ export class InterfacesComponent implements OnInit {
implementationNamespace: string = null;
implementation: GenerateData = new GenerateData();
artifactTemplate: GenerateData = new GenerateData();
artifactTypes: ArtifactTypeSelectData[];
modalOpen: boolean;

constructor(private service: InterfacesService, private notify: WineryNotificationService,
public sharedData: InstanceService, private existService: ExistService,
private route: Router) {
private artifactService: WineryArtifactService, private route: Router) {
}

ngOnInit() {
Expand All @@ -91,6 +95,10 @@ export class InterfacesComponent implements OnInit {
data => this.handleInheritedInterfaceData(data),
error => this.handleError(error)
);
this.artifactService.getAllArtifactTypes().subscribe(
res => this.handleArtifactTypeData(res),
error => this.handleError(error)
);
this.toscaType = this.sharedData.toscaComponent.toscaType;
this.isServiceTemplate = this.toscaType === ToscaTypes.ServiceTemplate;
}
Expand Down Expand Up @@ -200,9 +208,12 @@ export class InterfacesComponent implements OnInit {
showGenerateImplementationModal(): void {
this.artifactTemplate.name = this.sharedData.toscaComponent.localNameWithoutVersion
+ '-' + this.sharedData.currentVersion.toString()
+ '-' + this.selectedInterface.name.replace(/\W/g, '-')
+ '-' + this.getSelectedInterfaceOrOperationName()
+ '-IA';

this.artifactTemplate.selectedInterface = this.selectedInterface;
if (this.selectedOperation) {
this.artifactTemplate.selectedOperation = this.selectedOperation;
}
let artifactTemplateNamespace = this.sharedData.toscaComponent.namespace;
if (this.sharedData.toscaComponent.namespace.includes('nodetypes')) {
artifactTemplateNamespace = this.sharedData.toscaComponent.namespace
Expand All @@ -216,15 +227,6 @@ export class InterfacesComponent implements OnInit {
this.artifactTemplate.toscaType = ToscaTypes.ArtifactTemplate;

this.generateArtifactApiData = new GenerateArtifactApiData();
const packageName = this.getPackageNameFromNamespace();

let javaPackageName = packageName;
if (packageName.includes('nodetypes')) {
javaPackageName = packageName.replace('nodetypes', 'nodetypeimplementations');
} else if (packageName.includes('relationshiptypes')) {
javaPackageName = packageName.replace('relationshiptypes', 'relationshiptypeimplementations');
}
this.generateArtifactApiData.javaPackage = javaPackageName;

this.generateArtifactApiData.autoCreateArtifactTemplate = 'yes';
this.generateArtifactApiData.interfaceName = this.selectedInterface.name;
Expand Down Expand Up @@ -253,7 +255,13 @@ export class InterfacesComponent implements OnInit {
this.generateArtifactApiData.artifactTemplateName = this.artifactTemplate.name;
this.generateArtifactApiData.artifactTemplateNamespace = this.artifactTemplate.namespace;
this.generateArtifactApiData.artifactName = this.generateArtifactApiData.artifactTemplateName;
// Fix this prevent weired renaming by backend
if (this.artifactTemplate.selectedOperation.name === this.removeNSFromName(this.artifactTemplate.selectedInterface.name)) {
// Implement whole interface
this.generateArtifactApiData.operationName = 'interface';
} else {
this.generateArtifactApiData.operationName = this.artifactTemplate.selectedOperation.name;
}
// Fix this prevent weird renaming by backend
this.generateArtifactApiData.artifactTemplate = null;
// Save the current interfaces & operations first in order to prevent inconsistencies.
this.save();
Expand All @@ -262,6 +270,7 @@ export class InterfacesComponent implements OnInit {
// endregion

// region ########## Generate Lifecycle Interface ##########

generateLifecycleInterface(): void {
const lifecycle = new InterfacesApiData();
if (this.toscaType === ToscaTypes.RelationshipType && this.route.url.endsWith('/interfaces')) {
Expand All @@ -282,7 +291,6 @@ export class InterfacesComponent implements OnInit {
this.interfacesData.push(lifecycle);
this.interfaceComponent.selectItem(lifecycle);
}

containsDefaultLifecycle(): boolean {
if (this.sharedData.currentVersion.editable) {
if (this.interfacesData === null || this.interfacesData === undefined) {
Expand All @@ -300,6 +308,7 @@ export class InterfacesComponent implements OnInit {
// endregion

// region ######### Checker ##########

checkImplementationExists(): void {
if (!this.implementationNamespace.endsWith('/')) {
this.existService.check(backendBaseURL + '/'
Expand All @@ -312,7 +321,6 @@ export class InterfacesComponent implements OnInit {
);
}
}

checkArtifactTemplateExists(): void {
if (!this.generateArtifactApiData.artifactTemplateNamespace.endsWith('/')) {
this.existService.check(backendBaseURL + '/artifacttemplates/'
Expand Down Expand Up @@ -396,28 +404,31 @@ export class InterfacesComponent implements OnInit {
}
}

handleCancel() {
this.modalOpen = false;
}

// endregion

// region ########## Private Methods ##########

private handleInterfacesApiData(data: InterfacesApiData[]) {
this.interfacesData = data ? data : [];

}

private handleInheritedInterfaceData(data: InheritedInterface[]) {

this.inheritedInterfacesData = data ? data : [];

}

private handleSave() {

this.notify.success('Changes saved!');

// If there is a generation of implementations in progress, generate those now.
if (this.generating) {
this.implementation.name += WineryVersion.WINERY_NAME_FROM_VERSION_SEPARATOR + this.implementation.version.toString();
if (this.implementation.createComponent) {
this.implementation.name += WineryVersion.WINERY_NAME_FROM_VERSION_SEPARATOR + this.implementation.version.toString();
this.service.createImplementation(this.implementation.name, this.implementation.namespace)
.subscribe(
data => this.handleGeneratedImplementation(data),
Expand All @@ -432,34 +443,17 @@ export class InterfacesComponent implements OnInit {
}

private handleError(error: HttpErrorResponse) {

console.log(error);
this.generating = false;
this.notify.error(error.error);
}

private getPackageNameFromNamespace(): string {
// to only get the relevant information, without the 'http://'
const namespaceArray = this.sharedData.toscaComponent.namespace.split('/').slice(2);
const domainArray = namespaceArray[0].split('.');

let javaPackage = '';
for (let i = domainArray.length - 1; i >= 0; i--) {
if (javaPackage.length > 0) {
javaPackage += '.';
}
javaPackage += domainArray[i];
}
for (let i = 1; i < namespaceArray.length; i++) {
javaPackage += '.' + namespaceArray[i];
}

return javaPackage;
}

private handleGeneratedImplementation(data?: any) {
if (this.artifactTemplate.createComponent) {
this.generateArtifactApiData.artifactTemplateName = this.generateArtifactApiData.artifactName = this.artifactTemplate.name;
this.generateArtifactApiData.artifactTemplateNamespace = this.artifactTemplate.namespace;
this.generateArtifactApiData.artifactType = this.artifactTemplate.artifactTypeQName;
console.log(this.generateArtifactApiData);
this.service.createArtifactTemplate(this.implementation.name, this.implementation.namespace, this.generateArtifactApiData)
.subscribe(
(response) => this.handleGeneratedArtifact(response),
Expand All @@ -474,7 +468,8 @@ export class InterfacesComponent implements OnInit {
}
}

private handleGeneratedArtifact(response: HttpResponse<string>) {
private handleGeneratedArtifact(response: HttpResponse<IAReport>) {
const report: IAReport = response.body;
let message = '';
if (this.toscaType === ToscaTypes.NodeType) {
// backend return a path to the created artifacttemplate in the form: http://localhost:8080/winery/
Expand All @@ -485,9 +480,30 @@ export class InterfacesComponent implements OnInit {
}
this.generating = false;
this.generateImplModal.hide();
this.notify.success(message, 'Successfully created Artifact!', { enableHTML: true });
if (report.warning !== undefined && report.warning.length > 0) {
this.notify.warning(report.warning);
} else {
this.notify.success(message, 'Successfully created Artifact!', { enableHTML: true });
}
}

// endregion

private handleArtifactTypeData(res: any) {
this.artifactTypes = res;
}

private getSelectedInterfaceOrOperationName() {
// If there is only one operation, or none is selected, we just implement the whole interface. As such, we name the ArtifactTemplate accordingly.
if (this.selectedInterface.operations.length === 1 || !this.selectedOperation) {
return this.removeNSFromName(this.selectedInterface.name);
}
return this.removeNSFromName(this.selectedOperation.name);
}

private removeNSFromName(name: string) {
// Assumption: the actual interface name does not contain any '/'
// Also works if there is no NS prefixing the name
return name.substr(name.lastIndexOf('/') + 1);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Contributors to the Eclipse Foundation
* Copyright (c) 2017-2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand Down Expand Up @@ -28,6 +28,7 @@ import { WineryIoParameterModule } from '../../../wineryIoParameter/wineryIoPara
import { WineryTargetInterfaceModule } from './targetInterface/wineryTargetInterface.module';
import { WineryComponentExistsModule } from '../../../wineryComponentExists/wineryComponentExists.module';
import { SelectModule } from 'ng2-select';
import { WineryArtifactService } from '../wineryArtifacts/artifact.service';

@NgModule({
imports: [
Expand All @@ -50,7 +51,8 @@ import { SelectModule } from 'ng2-select';
InterfacesComponent,
],
providers: [
ExistService
ExistService,
WineryArtifactService
],
})
export class InterfacesModule {
Expand Down
Loading

0 comments on commit 49a4536

Please sign in to comment.