001package org.nasdanika.html.flow; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.List; 006import java.util.Map; 007import java.util.function.Predicate; 008import java.util.stream.Collectors; 009 010import org.eclipse.emf.common.util.EList; 011import org.eclipse.emf.common.util.URI; 012import org.eclipse.emf.ecore.EObject; 013import org.eclipse.emf.ecore.ETypedElement; 014import org.nasdanika.common.Context; 015import org.nasdanika.common.ProgressMonitor; 016import org.nasdanika.common.Util; 017import org.nasdanika.diagram.Diagram; 018import org.nasdanika.diagram.DiagramElement; 019import org.nasdanika.flow.Call; 020import org.nasdanika.flow.FlowElement; 021import org.nasdanika.flow.FlowPackage; 022import org.nasdanika.flow.Participant; 023import org.nasdanika.flow.Transition; 024import org.nasdanika.flow.util.FlowStateDiagramGenerator; 025import org.nasdanika.html.emf.ColumnBuilder; 026import org.nasdanika.html.model.app.Action; 027import org.nasdanika.html.model.bootstrap.TableCell; 028import org.nasdanika.ncore.NamedElement; 029import org.nasdanika.ncore.NcorePackage; 030import org.nasdanika.ncore.util.NamedElementComparator; 031 032public class FlowElementActionBuilder<T extends FlowElement<?>> extends ParticipantResponsibilityActionBuilder<T> { 033 034 public FlowElementActionBuilder(T value, Context context) { 035 super(value, context); 036 } 037 038 @Override 039 protected List<ETypedElement> getProperties() { 040 List<ETypedElement> properties = super.getProperties(); 041 properties.add(FlowPackage.Literals.FLOW_ELEMENT__INPUT_ARTIFACTS); 042 properties.add(FlowPackage.Literals.FLOW_ELEMENT__OUTPUT_ARTIFACTS); 043 properties.add(FlowPackage.Literals.FLOW_ELEMENT__PARTICIPANTS); 044 properties.add(FlowPackage.Literals.FLOW_ELEMENT__RESOURCES); 045 return properties; 046 } 047 048 @SuppressWarnings("unchecked") 049 @Override 050 protected Object getTypedElementValue(ETypedElement typedElement) throws Exception { 051 Object value = super.getTypedElementValue(typedElement); 052 if (value instanceof Collection && ( 053 typedElement == FlowPackage.Literals.FLOW_ELEMENT__INPUT_ARTIFACTS 054 || typedElement == FlowPackage.Literals.FLOW_ELEMENT__OUTPUT_ARTIFACTS 055 || typedElement == FlowPackage.Literals.FLOW_ELEMENT__PARTICIPANTS 056 || typedElement == FlowPackage.Literals.FLOW_ELEMENT__RESOURCES)) { 057 return ((Collection<NamedElement>) value).stream().sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList()); 058 } 059 return value; 060 } 061 062 @Override 063 protected void resolve( 064 Action action, 065 org.nasdanika.html.emf.EObjectActionResolver.Context context, 066 ProgressMonitor progressMonitor) throws Exception { 067 068 super.resolve(action, context, progressMonitor); 069 070 // Inputs 071 EList<Action> sections = action.getSections(); 072 if (!getTarget().getInputs().isEmpty()) { 073 sections.add(createInputsAction(action, context, progressMonitor)); 074 } 075 076 // Outputs 077 if (!getTarget().getOutputs().isEmpty()) { 078 sections.add(createOutputsAction(action, context, progressMonitor)); 079 } 080 081 // Invocations 082 if (!getTarget().getInvocations().isEmpty()) { 083 sections.add(createInvocationsAction(action, context, progressMonitor)); 084 } 085 086 // Calls 087 if (!getTarget().getCalls().isEmpty()) { 088 sections.add(createCallsAction(action, context, progressMonitor)); 089 } 090 091 // Artifact participant responsibilities 092 if (!getTarget().getArtifactResponsibilities().isEmpty()) { 093 sections.add(createArtifactResponsibilitiesAction(action, context, progressMonitor)); 094 } 095 } 096 097 @Override 098 protected void populateRepresentation( 099 Diagram representation, 100 Action action, 101 org.nasdanika.html.emf.EObjectActionResolver.Context context, 102 ProgressMonitor progressMonitor) 103 throws Exception { 104 105 FlowStateDiagramGenerator flowStateDiagramGenerator = new FlowStateDiagramGenerator() { 106 107 @Override 108 protected String getFlowElementLocation(FlowElement<?> flowElement) { 109 Action elementAction = context.getAction(flowElement); 110 if (elementAction == null) { 111 return null; 112 } 113 114 URI uri = context.resolve(elementAction, action); 115 return uri == null ? null : uri.toString(); 116 } 117 118 @Override 119 protected String getFlowElementTooltip(FlowElement<?> flowElement) { 120 Action elementAction = context.getAction(flowElement); 121 return elementAction == null ? null : elementAction.getDescription(); 122 } 123 124 @Override 125 protected String getParticipantLocation(Participant participant) { 126 Action elementAction = context.getAction(participant); 127 if (elementAction == null) { 128 return null; 129 } 130 131 URI uri = context.resolve(elementAction, action); 132 return uri == null ? null : uri.toString(); 133 } 134 135 @Override 136 protected String getParticipantTooltip(Participant participant) { 137 Action elementAction = context.getAction(participant); 138 return elementAction == null ? null : elementAction.getDescription(); 139 } 140 141 /** 142 * Wraps text 143 */ 144 @Override 145 protected DiagramElement createDiagramElement( 146 FlowElement<?> flowElement, 147 Map<FlowElement<?>, DiagramElement> semanticMap, 148 FlowElement<?> contextElement, 149 Predicate<FlowElement<?>> partitionPredicate, 150 int depth) { 151 152 DiagramElement ret = super.createDiagramElement(flowElement, semanticMap, contextElement, partitionPredicate, depth); 153 String text = ret.getText(); 154 int initialLineLength = 25; 155 if (text != null && text.length() > initialLineLength) { 156 ret.setText(Util.wrap(text, initialLineLength, 2, "\\n")); 157 } 158 return ret; 159 } 160 161 }; 162 163 populateRepresentation(representation, flowStateDiagramGenerator); 164 } 165 166 protected void populateRepresentation(Diagram representation, FlowStateDiagramGenerator flowStateDiagramGenerator) { 167 flowStateDiagramGenerator.generateDiagram(getTarget(), representation, null); 168 } 169 170 private Action createInputsAction( 171 Action action, 172 org.nasdanika.html.emf.EObjectActionResolver.Context context, 173 ProgressMonitor progressMonitor) throws Exception { 174 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 175 columnBuilders.add(new ColumnBuilder<EObject>() { 176 177 @Override 178 public void buildHeader( 179 TableCell header, 180 Action base, 181 ETypedElement typedElement, 182 org.nasdanika.html.emf.EObjectActionResolver.Context context, 183 ProgressMonitor progressMonitor) 184 throws Exception { 185 header.getContent().add(createText("Source")); 186 } 187 188 @Override 189 public void buildCell( 190 EObject rowElement, 191 TableCell cell, 192 Action base, 193 ETypedElement typedElement, 194 org.nasdanika.html.emf.EObjectActionResolver.Context context, 195 ProgressMonitor progressMonitor) 196 throws Exception { 197 cell.getContent().add(renderValue(base, typedElement, rowElement.eContainer().eContainer(), context, progressMonitor)); 198 } 199 }); 200 201 columnBuilders.add(createColumnBuilder(NcorePackage.Literals.NAMED_ELEMENT__NAME)); 202 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.PACKAGE_ELEMENT__DOCUMENTATION)); 203 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.TRANSITION__PAYLOAD)); 204 205 return createTableAction( 206 FlowPackage.Literals.FLOW_ELEMENT__INPUTS, 207 columnBuilders, 208 action, 209 context, 210 progressMonitor); 211 } 212 213 private Action createOutputsAction( 214 Action action, 215 org.nasdanika.html.emf.EObjectActionResolver.Context context, 216 ProgressMonitor progressMonitor) throws Exception { 217 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 218 columnBuilders.add(new ColumnBuilder<EObject>() { 219 220 @Override 221 public void buildHeader( 222 TableCell header, 223 Action base, 224 ETypedElement typedElement, 225 org.nasdanika.html.emf.EObjectActionResolver.Context context, 226 ProgressMonitor progressMonitor) 227 throws Exception { 228 header.getContent().add(createText("Key")); 229 } 230 231 @Override 232 public void buildCell( 233 EObject rowElement, 234 TableCell cell, 235 Action base, 236 ETypedElement typedElement, 237 org.nasdanika.html.emf.EObjectActionResolver.Context context, 238 ProgressMonitor progressMonitor) 239 throws Exception { 240 EObject renderedValue = renderValue(base, typedElement, ((Map.Entry<?,?>) rowElement).getKey(), context, progressMonitor); 241 if (renderedValue != null) { 242 cell.getContent().add(renderedValue); 243 } 244 } 245 }); 246 247 columnBuilders.add(new ColumnBuilder<EObject>() { 248 249 @Override 250 public void buildHeader( 251 TableCell header, 252 Action base, 253 ETypedElement typedElement, 254 org.nasdanika.html.emf.EObjectActionResolver.Context context, 255 ProgressMonitor progressMonitor) 256 throws Exception { 257 header.getContent().add(createText("Target")); 258 } 259 260 @Override 261 public void buildCell( 262 EObject rowElement, 263 TableCell cell, 264 Action base, 265 ETypedElement typedElement, 266 org.nasdanika.html.emf.EObjectActionResolver.Context context, 267 ProgressMonitor progressMonitor) 268 throws Exception { 269 Transition transition = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 270 EObject renderedValue = renderValue(base, typedElement, transition.getTarget(), context, progressMonitor); 271 if (renderedValue != null) { 272 cell.getContent().add(renderedValue); 273 } 274 } 275 }); 276 277 columnBuilders.add(new ColumnBuilder<EObject>() { 278 279 @Override 280 public void buildHeader( 281 TableCell header, 282 Action base, 283 ETypedElement typedElement, 284 org.nasdanika.html.emf.EObjectActionResolver.Context context, 285 ProgressMonitor progressMonitor) 286 throws Exception { 287 header.getContent().add(createText("Name")); 288 } 289 290 @Override 291 public void buildCell( 292 EObject rowElement, 293 TableCell cell, 294 Action base, 295 ETypedElement typedElement, 296 org.nasdanika.html.emf.EObjectActionResolver.Context context, 297 ProgressMonitor progressMonitor) 298 throws Exception { 299 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 300 EObject renderedValue = renderValue(base, typedElement, value.getName(), context, progressMonitor); 301 if (renderedValue != null) { 302 cell.getContent().add(renderedValue); 303 } 304 } 305 }); 306 307 columnBuilders.add(new ColumnBuilder<EObject>() { 308 309 @Override 310 public void buildHeader( 311 TableCell header, 312 Action base, 313 ETypedElement typedElement, 314 org.nasdanika.html.emf.EObjectActionResolver.Context context, 315 ProgressMonitor progressMonitor) 316 throws Exception { 317 header.getContent().add(createText("Documentation")); 318 } 319 320 @Override 321 public void buildCell( 322 EObject rowElement, 323 TableCell cell, 324 Action base, 325 ETypedElement typedElement, 326 org.nasdanika.html.emf.EObjectActionResolver.Context context, 327 ProgressMonitor progressMonitor) 328 throws Exception { 329 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 330 EObject renderedValue = renderValue(base, typedElement, value.getDocumentation(), context, progressMonitor); 331 if (renderedValue != null) { 332 cell.getContent().add(renderedValue); 333 } 334 } 335 }); 336 337 columnBuilders.add(new ColumnBuilder<EObject>() { 338 339 @Override 340 public void buildHeader( 341 TableCell header, 342 Action base, 343 ETypedElement typedElement, 344 org.nasdanika.html.emf.EObjectActionResolver.Context context, 345 ProgressMonitor progressMonitor) 346 throws Exception { 347 header.getContent().add(createText("Payload")); 348 } 349 350 @Override 351 public void buildCell( 352 EObject rowElement, 353 TableCell cell, 354 Action base, 355 ETypedElement typedElement, 356 org.nasdanika.html.emf.EObjectActionResolver.Context context, 357 ProgressMonitor progressMonitor) 358 throws Exception { 359 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 360 EObject renderedValue = renderValue(base, typedElement, value.getPayload(), context, progressMonitor); 361 if (renderedValue != null) { 362 cell.getContent().add(renderedValue); 363 } 364 } 365 }); 366 367 return createTableAction( 368 FlowPackage.Literals.FLOW_ELEMENT__OUTPUTS, 369 columnBuilders, 370 action, 371 context, 372 progressMonitor); 373 } 374 375 private Action createInvocationsAction( 376 Action action, 377 org.nasdanika.html.emf.EObjectActionResolver.Context context, 378 ProgressMonitor progressMonitor) throws Exception { 379 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 380 columnBuilders.add(new ColumnBuilder<EObject>() { 381 382 @Override 383 public void buildHeader( 384 TableCell header, 385 Action base, 386 ETypedElement typedElement, 387 org.nasdanika.html.emf.EObjectActionResolver.Context context, 388 ProgressMonitor progressMonitor) 389 throws Exception { 390 header.getContent().add(createText("Source")); 391 } 392 393 @Override 394 public void buildCell( 395 EObject rowElement, 396 TableCell cell, 397 Action base, 398 ETypedElement typedElement, 399 org.nasdanika.html.emf.EObjectActionResolver.Context context, 400 ProgressMonitor progressMonitor) 401 throws Exception { 402 cell.getContent().add(renderValue(base, typedElement, rowElement.eContainer().eContainer(), context, progressMonitor)); 403 } 404 }); 405 406 columnBuilders.add(createColumnBuilder(NcorePackage.Literals.NAMED_ELEMENT__NAME)); 407 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.PACKAGE_ELEMENT__DOCUMENTATION)); 408 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.TRANSITION__PAYLOAD)); 409 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.CALL__RESPONSE)); 410 411 return createTableAction( 412 FlowPackage.Literals.FLOW_ELEMENT__INVOCATIONS, 413 columnBuilders, 414 action, 415 context, 416 progressMonitor); 417 } 418 419 private Action createCallsAction( 420 Action action, 421 org.nasdanika.html.emf.EObjectActionResolver.Context context, 422 ProgressMonitor progressMonitor) throws Exception { 423 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 424 columnBuilders.add(new ColumnBuilder<EObject>() { 425 426 @Override 427 public void buildHeader( 428 TableCell header, 429 Action base, 430 ETypedElement typedElement, 431 org.nasdanika.html.emf.EObjectActionResolver.Context context, 432 ProgressMonitor progressMonitor) 433 throws Exception { 434 header.getContent().add(createText("Key")); 435 } 436 437 @Override 438 public void buildCell( 439 EObject rowElement, 440 TableCell cell, 441 Action base, 442 ETypedElement typedElement, 443 org.nasdanika.html.emf.EObjectActionResolver.Context context, 444 ProgressMonitor progressMonitor) 445 throws Exception { 446 EObject renderedValue = renderValue(base, typedElement, ((Map.Entry<?,?>) rowElement).getKey(), context, progressMonitor); 447 if (renderedValue != null) { 448 cell.getContent().add(renderedValue); 449 } 450 } 451 }); 452 453 columnBuilders.add(new ColumnBuilder<EObject>() { 454 455 @Override 456 public void buildHeader( 457 TableCell header, 458 Action base, 459 ETypedElement typedElement, 460 org.nasdanika.html.emf.EObjectActionResolver.Context context, 461 ProgressMonitor progressMonitor) 462 throws Exception { 463 header.getContent().add(createText("Target")); 464 } 465 466 @Override 467 public void buildCell( 468 EObject rowElement, 469 TableCell cell, 470 Action base, 471 ETypedElement typedElement, 472 org.nasdanika.html.emf.EObjectActionResolver.Context context, 473 ProgressMonitor progressMonitor) 474 throws Exception { 475 Transition transition = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 476 EObject renderedValue = renderValue(base, typedElement, transition.getTarget(), context, progressMonitor); 477 if (renderedValue != null) { 478 cell.getContent().add(renderedValue); 479 } 480 } 481 }); 482 483 columnBuilders.add(new ColumnBuilder<EObject>() { 484 485 @Override 486 public void buildHeader( 487 TableCell header, 488 Action base, 489 ETypedElement typedElement, 490 org.nasdanika.html.emf.EObjectActionResolver.Context context, 491 ProgressMonitor progressMonitor) 492 throws Exception { 493 header.getContent().add(createText("Name")); 494 } 495 496 @Override 497 public void buildCell( 498 EObject rowElement, 499 TableCell cell, 500 Action base, 501 ETypedElement typedElement, 502 org.nasdanika.html.emf.EObjectActionResolver.Context context, 503 ProgressMonitor progressMonitor) 504 throws Exception { 505 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 506 EObject renderedValue = renderValue(base, typedElement, value.getName(), context, progressMonitor); 507 if (renderedValue != null) { 508 cell.getContent().add(renderedValue); 509 } 510 } 511 }); 512 513 columnBuilders.add(new ColumnBuilder<EObject>() { 514 515 @Override 516 public void buildHeader( 517 TableCell header, 518 Action base, 519 ETypedElement typedElement, 520 org.nasdanika.html.emf.EObjectActionResolver.Context context, 521 ProgressMonitor progressMonitor) 522 throws Exception { 523 header.getContent().add(createText("Documentation")); 524 } 525 526 @Override 527 public void buildCell( 528 EObject rowElement, 529 TableCell cell, 530 Action base, 531 ETypedElement typedElement, 532 org.nasdanika.html.emf.EObjectActionResolver.Context context, 533 ProgressMonitor progressMonitor) 534 throws Exception { 535 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 536 EObject renderedValue = renderValue(base, typedElement, value.getDocumentation(), context, progressMonitor); 537 if (renderedValue != null) { 538 cell.getContent().add(renderedValue); 539 } 540 } 541 }); 542 543 columnBuilders.add(new ColumnBuilder<EObject>() { 544 545 @Override 546 public void buildHeader( 547 TableCell header, 548 Action base, 549 ETypedElement typedElement, 550 org.nasdanika.html.emf.EObjectActionResolver.Context context, 551 ProgressMonitor progressMonitor) 552 throws Exception { 553 header.getContent().add(createText("Request")); 554 } 555 556 @Override 557 public void buildCell( 558 EObject rowElement, 559 TableCell cell, 560 Action base, 561 ETypedElement typedElement, 562 org.nasdanika.html.emf.EObjectActionResolver.Context context, 563 ProgressMonitor progressMonitor) 564 throws Exception { 565 Transition value = (Transition) ((Map.Entry<?,?>) rowElement).getValue(); 566 EObject renderedValue = renderValue(base, typedElement, value.getPayload(), context, progressMonitor); 567 if (renderedValue != null) { 568 cell.getContent().add(renderedValue); 569 } 570 } 571 }); 572 573 columnBuilders.add(new ColumnBuilder<EObject>() { 574 575 @Override 576 public void buildHeader( 577 TableCell header, 578 Action base, 579 ETypedElement typedElement, 580 org.nasdanika.html.emf.EObjectActionResolver.Context context, 581 ProgressMonitor progressMonitor) 582 throws Exception { 583 header.getContent().add(createText("Response")); 584 } 585 586 @Override 587 public void buildCell( 588 EObject rowElement, 589 TableCell cell, 590 Action base, 591 ETypedElement typedElement, 592 org.nasdanika.html.emf.EObjectActionResolver.Context context, 593 ProgressMonitor progressMonitor) 594 throws Exception { 595 Call value = (Call) ((Map.Entry<?,?>) rowElement).getValue(); 596 EObject renderedValue = renderValue(base, typedElement, value.getResponse(), context, progressMonitor); 597 if (renderedValue != null) { 598 cell.getContent().add(renderedValue); 599 } 600 } 601 }); 602 603 return createTableAction( 604 FlowPackage.Literals.FLOW_ELEMENT__CALLS, 605 columnBuilders, 606 action, 607 context, 608 progressMonitor); 609 } 610 611 612 private Action createArtifactResponsibilitiesAction( 613 Action action, 614 org.nasdanika.html.emf.EObjectActionResolver.Context context, 615 ProgressMonitor progressMonitor) throws Exception { 616 617 return createTableAction( 618 FlowPackage.Literals.FLOW_ELEMENT__ARTIFACT_RESPONSIBILITIES, 619 action, 620 context, 621 progressMonitor, 622 FlowPackage.Literals.ARTIFACT_PARTICIPANT_RESPONSIBILITY__ARTIFACT, 623 FlowPackage.Literals.PARTICIPANT_RESPONSIBILITY__RESPONSIBLE, 624 FlowPackage.Literals.PARTICIPANT_RESPONSIBILITY__ACCOUNTABLE, 625 FlowPackage.Literals.PARTICIPANT_RESPONSIBILITY__CONSULTED, 626 FlowPackage.Literals.PARTICIPANT_RESPONSIBILITY__INFORMED, 627 NcorePackage.Literals.MODEL_ELEMENT__DESCRIPTION); 628 } 629 630}