Skip to content

[PF-66] Model inheritance in JS #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: release/3.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions src/lib/export/export-utils.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {
Action,
ActionType,
Arc,
ArcType,
CaseLogic,
Event,
Expression,
Extension,
I18nString,
I18nWithDynamic,
Logic, Option,
PetriflowFunction,
XmlArcType
Logic,
Option,
PetriflowFunction
} from '../model';

export class ExportUtils {
Expand Down Expand Up @@ -48,7 +47,7 @@ export class ExportUtils {
}] : undefined, value?.dynamic);
}

public exportOption(doc: Element, name: string, value : Option | undefined): void {
public exportOption(doc: Element, name: string, value: Option | undefined): void {
const attributes = [];
if (value?.key) {
attributes.push({
Expand Down Expand Up @@ -164,14 +163,6 @@ export class ExportUtils {
element.appendChild(exportLogic);
}

public exportArcType(type: ArcType): XmlArcType {
const xmlType = Arc.arcTypeMapping.get(type);
if (!xmlType) {
throw new Error(`Unknown export mapping for arc type ${type}`);
}
return xmlType;
}

public transformKebabCaseToCamelCase(stringToTransform: string): string {
return stringToTransform.replace(/-./g, x => x[1].toUpperCase());
}
Expand All @@ -191,4 +182,15 @@ export class ExportUtils {
}]));
doc.appendChild(tagsElement);
}

public exportExtension(doc: Element, name: string, extension: Extension | undefined): void {
if (extension === undefined) {
return
}
const extensionElement = this.xmlConstructor.createElement(name);
['id', 'version'].forEach(extensionAttribute => {
this.exportTag(extensionElement, extensionAttribute, extension[extensionAttribute as keyof Extension]?.toString());
});
doc.appendChild(extensionElement);
}
}
5 changes: 2 additions & 3 deletions src/lib/export/export.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export class ExportService {
this._exportUtils.exportTag(doc, 'icon', model.icon);
this._exportUtils.exportTag(doc, 'defaultRole', model.defaultRole !== undefined ? (model.defaultRole.toString()) : '');
this._exportUtils.exportTag(doc, 'anonymousRole', model.anonymousRole !== undefined ? (model.anonymousRole.toString()) : '');
this._exportUtils.exportTags(doc, model.tags);
this._exportUtils.exportI18nWithDynamic(doc, 'caseName', model.caseName);
this._exportUtils.exportExtension(doc, 'extends', model.extends);
}

public exportRoles(doc: Element, model: PetriNet): void {
Expand Down Expand Up @@ -276,7 +276,6 @@ export class ExportService {
this._exportUtils.exportTag(exportTrans, 'x', trans.x?.toString(), true);
this._exportUtils.exportTag(exportTrans, 'y', trans.y?.toString(), true);
this._exportUtils.exportI18nString(exportTrans, 'title', trans.title, true);
this._exportUtils.exportTags(exportTrans, trans.tags);
this._exportUtils.exportTag(exportTrans, 'icon', trans.icon ?? '');
this._exportUtils.exportTag(exportTrans, 'assignPolicy', trans.assignPolicy === AssignPolicy.MANUAL ? '' : trans.assignPolicy);
this._exportUtils.exportTag(exportTrans, 'finishPolicy', trans.finishPolicy === FinishPolicy.MANUAL ? '' : trans.finishPolicy);
Expand Down Expand Up @@ -672,7 +671,7 @@ export class ExportService {
model.getArcs().sort((a, b) => a.compare(b)).forEach(arc => {
const exportArc = this.xmlConstructor.createElement('arc');
this._exportUtils.exportTag(exportArc, 'id', arc.id, true);
this._exportUtils.exportTag(exportArc, 'type', this._exportUtils.exportArcType(arc.type));
this._exportUtils.exportTag(exportArc, 'type', arc.type);
this._exportUtils.exportTag(exportArc, 'sourceId', arc.source.id);
this._exportUtils.exportTag(exportArc, 'destinationId', arc.destination.id);
this._exportUtils.exportExpression(exportArc, 'multiplicity', arc.multiplicity);
Expand Down
62 changes: 30 additions & 32 deletions src/lib/import/import-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Action,
ActionType,
ArcType,
Component,
DataEvent,
DataEventType,
Expand All @@ -9,6 +10,7 @@ import {
Event,
EventPhase,
Expression,
Extension,
FlexAlignContent,
FlexAlignItems,
FlexContainer,
Expand Down Expand Up @@ -40,8 +42,7 @@ import {
Property,
TransitionPermissionRef,
Trigger,
TriggerType,
XmlArcType
TriggerType
} from '../model';
import {IdentifierBlacklist} from '../model/identifier-blacklist';

Expand Down Expand Up @@ -71,17 +72,24 @@ export class ImportUtils {
return i18n;
}

public parseIdentifier(xmlTag: Element | Document | null, child: string): string {
const xmlIdentifierString = this.tagValue(xmlTag, child);
public parseIdentifierFromChildElement(xmlTag: Element | Document | null, child: string): string {
return this.validateIdentifier(this.tagValue(xmlTag, child), xmlTag?.nodeName);
}

public parseIdentifierFromAttribute(xmlTag: Element | null, child: string): string {
return this.validateIdentifier(this.tagAttribute(xmlTag, child), xmlTag?.nodeName);
}

private validateIdentifier(xmlIdentifierString: string, nodeName: string | undefined) {
if (xmlIdentifierString === '') {
throw new Error(`Id of ${xmlTag?.nodeName} must be defined`);
throw new Error(`Id of ${nodeName} must be defined`);
}
if (IdentifierBlacklist.identifierKeywords.has(xmlIdentifierString)) {
throw new Error(`Id of ${xmlTag?.nodeName} must not be Java or Groovy keyword, value [${xmlIdentifierString}]`);
throw new Error(`Id of ${nodeName} must not be Java or Groovy keyword, value [${xmlIdentifierString}]`);
}
const identifierRegex = new RegExp("^[$_a-zA-Z][_a-zA-Z0-9]*$");
if (!identifierRegex.test(xmlIdentifierString)) {
throw new Error(`Id of ${xmlTag?.nodeName} must be valid Java identifier, value [${xmlIdentifierString}]`);
throw new Error(`Id of ${nodeName} must be valid Java identifier, value [${xmlIdentifierString}]`);
}
return xmlIdentifierString;
}
Expand Down Expand Up @@ -173,7 +181,7 @@ export class ImportUtils {
if (!xmlComponent?.children || xmlComponent.children.length === 0) {
return undefined;
}
const comp = new Component(this.parseIdentifier(xmlComponent, 'id'));
const comp = new Component(this.parseIdentifierFromChildElement(xmlComponent, 'id'));
const properties = xmlComponent.getElementsByTagName('properties')[0];
if (properties?.children && properties.children.length > 0) {
for (const prop of Array.from(properties.getElementsByTagName('property'))) {
Expand Down Expand Up @@ -243,14 +251,14 @@ export class ImportUtils {

public parseRoleRef(xmlRoleRef: Element): TransitionPermissionRef {
const xmlRoleRefLogic = xmlRoleRef.getElementsByTagName('logic')[0];
const roleRef = new TransitionPermissionRef(this.parseIdentifier(xmlRoleRef, 'id'));
const roleRef = new TransitionPermissionRef(this.parseIdentifierFromChildElement(xmlRoleRef, 'id'));
this.resolveLogic(xmlRoleRefLogic, roleRef);
roleRef.properties = this.parseProperties(xmlRoleRef);
return roleRef;
}

public parseDataRef(xmlDataRef: Element): DataRef {
const dataRef = new DataRef(this.parseIdentifier(xmlDataRef, 'id'));
const dataRef = new DataRef(this.parseIdentifierFromChildElement(xmlDataRef, 'id'));
for (const xmlEvent of Array.from(xmlDataRef.getElementsByTagName('event'))) {
const event = new DataEvent(this.tagAttribute(xmlEvent, 'type') as DataEventType, '');
this.parseEvent(xmlEvent, event);
Expand All @@ -271,7 +279,7 @@ export class ImportUtils {
}

public parseGrid(xmlGrid: Element): GridContainer {
const grid = new GridContainer(this.parseIdentifier(xmlGrid, 'id'));
const grid = new GridContainer(this.parseIdentifierFromChildElement(xmlGrid, 'id'));

const properties = this.getChildElementByName(xmlGrid.children, 'properties');
if (properties) {
Expand Down Expand Up @@ -482,7 +490,7 @@ export class ImportUtils {
}

public parseFlex(xmlFlex: Element) {
const flex = new FlexContainer(this.parseIdentifier(xmlFlex, 'id'));
const flex = new FlexContainer(this.parseIdentifierFromChildElement(xmlFlex, 'id'));
const properties = this.getChildElementByName(xmlFlex.children, 'properties');
if (properties) {
flex.properties = this.parseFlexContainerProperties(properties);
Expand Down Expand Up @@ -616,16 +624,15 @@ export class ImportUtils {
return isStatic;
}

public parseArcType(xmlArc: Element): XmlArcType {
let parsedArcType = XmlArcType.REGULAR;
if (this.checkLengthAndNodes(xmlArc, 'type')) {
parsedArcType = xmlArc.getElementsByTagName('type')[0].childNodes[0].nodeValue as XmlArcType;
public parseArcType(xmlArc: Element): ArcType {
if (!this.checkLengthAndNodes(xmlArc, 'type')) {
throw new Error(`Type of arc with id ${this.parseIdentifierFromChildElement(xmlArc, 'id')} is undefined.`)
}
return parsedArcType;
return xmlArc.getElementsByTagName('type')[0].childNodes[0].nodeValue as ArcType;
}

public parseEvent<T>(xmlEvent: Element, event: Event<T>): void {
event.id = this.parseIdentifier(xmlEvent, 'id');
event.id = this.parseIdentifierFromChildElement(xmlEvent, 'id');
if (event.id === '') {
event.id = event.type + "_event_" + this.getNextEventId();
}
Expand Down Expand Up @@ -709,20 +716,11 @@ export class ImportUtils {
this.resetActionId();
}

parseTags(xmlDoc: Element | Document): Map<string, string> {
const tags = new Map<string, string>();
const tagsElement = xmlDoc.getElementsByTagName('tags')[0];
if (tagsElement?.children && tagsElement.children.length > 0) {
for (const tagElement of Array.from(xmlDoc.getElementsByTagName('tag'))) {
this.parseTag(tags, tagElement);
}
public parseExtension(xmlDoc: Document): Extension | undefined {
const xmlExtension = xmlDoc.getElementsByTagName('extends')[0];
if (xmlExtension === undefined) {
return undefined;
}
return tags;
}

parseTag(tags: Map<string, string>, tagElement: Element): void {
const key = this.tagAttribute(tagElement, 'key');
const value = tagElement.innerHTML;
tags.set(key, value);
return new Extension(this.tagValue(xmlExtension, 'id'), this.tagValue(xmlExtension, 'version'))
}
}
Loading