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.BiConsumer; 008import java.util.function.Consumer; 009import java.util.stream.Collectors; 010 011import org.eclipse.emf.common.util.EList; 012import org.eclipse.emf.common.util.EMap; 013import org.eclipse.emf.common.util.URI; 014import org.eclipse.emf.ecore.EObject; 015import org.eclipse.emf.ecore.EReference; 016import org.eclipse.emf.ecore.ETypedElement; 017import org.nasdanika.common.Context; 018import org.nasdanika.common.ProgressMonitor; 019import org.nasdanika.common.Util; 020import org.nasdanika.diagram.Diagram; 021import org.nasdanika.diagram.DiagramElement; 022import org.nasdanika.flow.Artifact; 023import org.nasdanika.flow.FlowPackage; 024import org.nasdanika.flow.Relationship; 025import org.nasdanika.flow.Transition; 026import org.nasdanika.flow.util.ArtifactComponentDiagramGenerator; 027import org.nasdanika.html.emf.ColumnBuilder; 028import org.nasdanika.html.model.app.Action; 029import org.nasdanika.html.model.app.AppFactory; 030import org.nasdanika.html.model.app.SectionStyle; 031import org.nasdanika.html.model.bootstrap.Table; 032import org.nasdanika.html.model.bootstrap.TableCell; 033import org.nasdanika.ncore.NcorePackage; 034import org.nasdanika.ncore.util.NamedElementComparator; 035 036public class ArtifactActionBuilder extends ParticipantResponsibilityActionBuilder<Artifact> { 037 038 public ArtifactActionBuilder(Artifact value, Context context) { 039 super(value, context); 040 } 041 042 @Override 043 protected Action buildAction( 044 Action action, 045 BiConsumer<EObject, Action> registry, 046 Consumer<org.nasdanika.common.Consumer<org.nasdanika.html.emf.EObjectActionResolver.Context>> resolveConsumer, 047 ProgressMonitor progressMonitor) throws Exception { 048 049 action = super.buildAction(action, registry, resolveConsumer, progressMonitor); 050 EList<EObject> children = action.getChildren(); 051 for (Artifact element: getTarget().getChildren().values().stream().sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList())) { 052 children.add(createChildAction(element, registry, resolveConsumer, progressMonitor)); 053 } 054 055 return action; 056 } 057 058 @Override 059 protected List<ETypedElement> getProperties() { 060 List<ETypedElement> properties = super.getProperties(); 061 properties.add(FlowPackage.Literals.ARTIFACT__INPUT_FOR); 062 properties.add(FlowPackage.Literals.ARTIFACT__OUTPUT_FOR); 063 properties.add(FlowPackage.Literals.ARTIFACT__REPOSITORIES); 064 properties.add(FlowPackage.Literals.ARTIFACT__USED_BY); 065 properties.add(FlowPackage.Literals.ARTIFACT__TEMPLATES); 066 properties.add(FlowPackage.Literals.ARTIFACT__INSTANCES); 067 return properties; 068 } 069 070 @Override 071 protected void resolve( 072 Action action, 073 org.nasdanika.html.emf.EObjectActionResolver.Context context, 074 ProgressMonitor progressMonitor) throws Exception { 075 076 super.resolve(action, context, progressMonitor); 077 078 EList<Action> sections = action.getSections(); 079 Artifact semanticElement = getTarget(); 080 if (!semanticElement.getPayloadFor().isEmpty()) { 081 sections.add(createEReferenceAction(action, FlowPackage.Literals.ARTIFACT__PAYLOAD_FOR, context, progressMonitor)); 082 } 083 084 if (!semanticElement.getResponseFor().isEmpty()) { 085 sections.add(createEReferenceAction(action, FlowPackage.Literals.ARTIFACT__RESPONSE_FOR, context, progressMonitor)); 086 } 087 088 089 // Inbound 090 EList<Relationship> inboundRelationships = semanticElement.getInboundRelationships(); 091 EMap<String, Relationship> outboundRelationships = semanticElement.getOutboundRelationships(); 092 if (!(inboundRelationships.isEmpty() && outboundRelationships.isEmpty())) { 093 Action rAction = AppFactory.eINSTANCE.createAction(); 094 rAction.setSectionStyle(SectionStyle.HEADER); 095 rAction.setText("Relationships"); 096 sections.add(rAction); 097 EList<Action> rSections = rAction.getSections(); 098 if (!inboundRelationships.isEmpty()) { 099 rSections.add(createInboundRelationshipsAction(action, context, progressMonitor)); 100 } 101 102 // Outbound 103 if (!outboundRelationships.isEmpty()) { 104 rSections.add(createOutboundRelationshipsAction(action, context, progressMonitor)); 105 } 106 } 107 108 } 109 110 // TODO - Sort by source 111 private Action createEReferenceAction( 112 Action action, 113 EReference eReference, 114 org.nasdanika.html.emf.EObjectActionResolver.Context context, 115 ProgressMonitor progressMonitor) throws Exception { 116 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 117 columnBuilders.add(new ColumnBuilder<EObject>() { 118 119 @Override 120 public void buildHeader( 121 TableCell header, 122 Action base, 123 ETypedElement typedElement, 124 org.nasdanika.html.emf.EObjectActionResolver.Context context, 125 ProgressMonitor progressMonitor) 126 throws Exception { 127 header.getContent().add(createText("Source")); 128 } 129 130 @Override 131 public void buildCell( 132 EObject rowElement, 133 TableCell cell, 134 Action base, 135 ETypedElement typedElement, 136 org.nasdanika.html.emf.EObjectActionResolver.Context context, 137 ProgressMonitor progressMonitor) 138 throws Exception { 139 cell.getContent().add(renderValue(base, typedElement, rowElement.eContainer().eContainer(), context, progressMonitor)); 140 } 141 }); 142 143 columnBuilders.add(new ColumnBuilder<EObject>() { 144 145 @Override 146 public void buildHeader( 147 TableCell header, 148 Action base, 149 ETypedElement typedElement, 150 org.nasdanika.html.emf.EObjectActionResolver.Context context, 151 ProgressMonitor progressMonitor) 152 throws Exception { 153 header.getContent().add(createText("Key")); 154 } 155 156 @Override 157 public void buildCell( 158 EObject rowElement, 159 TableCell cell, 160 Action base, 161 ETypedElement typedElement, 162 org.nasdanika.html.emf.EObjectActionResolver.Context context, 163 ProgressMonitor progressMonitor) 164 throws Exception { 165 EObject renderedValue = renderValue(base, typedElement, ((Map.Entry<?,?>) rowElement.eContainer()).getKey(), context, progressMonitor); 166 if (renderedValue != null) { 167 cell.getContent().add(renderedValue); 168 } 169 } 170 }); 171 172 columnBuilders.add(new ColumnBuilder<EObject>() { 173 174 @Override 175 public void buildHeader( 176 TableCell header, 177 Action base, 178 ETypedElement typedElement, 179 org.nasdanika.html.emf.EObjectActionResolver.Context context, 180 ProgressMonitor progressMonitor) 181 throws Exception { 182 header.getContent().add(createText("Target")); 183 } 184 185 @Override 186 public void buildCell( 187 EObject rowElement, 188 TableCell cell, 189 Action base, 190 ETypedElement typedElement, 191 org.nasdanika.html.emf.EObjectActionResolver.Context context, 192 ProgressMonitor progressMonitor) 193 throws Exception { 194 EObject renderedValue = renderValue(base, typedElement, ((Transition) rowElement).getTarget(), context, progressMonitor); 195 if (renderedValue != null) { 196 cell.getContent().add(renderedValue); 197 } 198 } 199 }); 200 201 columnBuilders.add(new ColumnBuilder<EObject>() { 202 203 @Override 204 public void buildHeader( 205 TableCell header, 206 Action base, 207 ETypedElement typedElement, 208 org.nasdanika.html.emf.EObjectActionResolver.Context context, 209 ProgressMonitor progressMonitor) 210 throws Exception { 211 header.getContent().add(createText("Name")); 212 } 213 214 @Override 215 public void buildCell( 216 EObject rowElement, 217 TableCell cell, 218 Action base, 219 ETypedElement typedElement, 220 org.nasdanika.html.emf.EObjectActionResolver.Context context, 221 ProgressMonitor progressMonitor) 222 throws Exception { 223 EObject renderedValue = renderValue(base, typedElement, ((Transition) rowElement).getName(), context, progressMonitor); 224 if (renderedValue != null) { 225 cell.getContent().add(renderedValue); 226 } 227 } 228 }); 229 230 columnBuilders.add(new ColumnBuilder<EObject>() { 231 232 @Override 233 public void buildHeader( 234 TableCell header, 235 Action base, 236 ETypedElement typedElement, 237 org.nasdanika.html.emf.EObjectActionResolver.Context context, 238 ProgressMonitor progressMonitor) 239 throws Exception { 240 header.getContent().add(createText("Documentation")); 241 } 242 243 @Override 244 public void buildCell( 245 EObject rowElement, 246 TableCell cell, 247 Action base, 248 ETypedElement typedElement, 249 org.nasdanika.html.emf.EObjectActionResolver.Context context, 250 ProgressMonitor progressMonitor) 251 throws Exception { 252 EObject renderedValue = renderValue(base, typedElement, ((Transition) rowElement).getDocumentation(), context, progressMonitor); 253 if (renderedValue != null) { 254 cell.getContent().add(renderedValue); 255 } 256 } 257 }); 258 259 return createTableAction( 260 eReference, 261 columnBuilders, 262 action, 263 context, 264 progressMonitor); 265 } 266 267 @Override 268 protected void populateRepresentation( 269 Diagram representation, 270 Action action, 271 org.nasdanika.html.emf.EObjectActionResolver.Context context, 272 ProgressMonitor progressMonitor) throws Exception { 273 274 ArtifactComponentDiagramGenerator artifactComponentDiagramGenerator = new ArtifactComponentDiagramGenerator() { 275 276 @Override 277 protected String getArtifactLocation(Artifact semanticElement) { 278 Action elementAction = context.getAction(semanticElement); 279 if (elementAction == null) { 280 return null; 281 } 282 283 URI uri = context.resolve(elementAction, action); 284 return uri == null ? null : uri.toString(); 285 } 286 287 @Override 288 protected String getArtifactTooltip(Artifact semanticElement) { 289 Action elementAction = context.getAction(semanticElement); 290 return elementAction == null ? null : elementAction.getDescription(); 291 } 292 293 @Override 294 protected DiagramElement createDiagramElement( 295 Artifact semanticElement, 296 Map<Artifact, DiagramElement> semanticMap, 297 Artifact contextElement, 298 int depth) { 299 300 DiagramElement ret = super.createDiagramElement(semanticElement, semanticMap, contextElement, depth); 301 String text = ret.getText(); 302 int initialLineLength = 25; 303 if (text != null && text.length() > initialLineLength) { 304 ret.setText(Util.wrap(text, initialLineLength, 2, "\\n")); 305 } 306 return ret; 307 } 308 309 }; 310 311 populateRepresentation(representation, artifactComponentDiagramGenerator); 312 } 313 314 protected void populateRepresentation(Diagram representation, ArtifactComponentDiagramGenerator artifactComponentDiagramGenerator) { 315 artifactComponentDiagramGenerator.generateDiagram(getTarget(), representation); 316 } 317 318 private Action createInboundRelationshipsAction( 319 Action action, 320 org.nasdanika.html.emf.EObjectActionResolver.Context context, 321 ProgressMonitor progressMonitor) throws Exception { 322 Collection<ColumnBuilder<? super EObject>> columnBuilders = new ArrayList<>(); 323 columnBuilders.add(new ColumnBuilder<EObject>() { 324 325 @Override 326 public void buildHeader( 327 TableCell header, 328 Action base, 329 ETypedElement typedElement, 330 org.nasdanika.html.emf.EObjectActionResolver.Context context, 331 ProgressMonitor progressMonitor) 332 throws Exception { 333 header.getContent().add(createText("Source")); 334 } 335 336 @Override 337 public void buildCell( 338 EObject rowElement, 339 TableCell cell, 340 Action base, 341 ETypedElement typedElement, 342 org.nasdanika.html.emf.EObjectActionResolver.Context context, 343 ProgressMonitor progressMonitor) 344 throws Exception { 345 cell.getContent().add(renderValue(base, typedElement, rowElement.eContainer().eContainer(), context, progressMonitor)); 346 } 347 }); 348 349 columnBuilders.add(createColumnBuilder(NcorePackage.Literals.NAMED_ELEMENT__NAME)); 350 columnBuilders.add(createColumnBuilder(FlowPackage.Literals.PACKAGE_ELEMENT__DOCUMENTATION)); 351 352 Action ret = AppFactory.eINSTANCE.createAction(); 353 ret.setText("Inbound"); 354 355 Table table = buildTable( 356 getTarget().getInboundRelationships(), 357 columnBuilders, 358 action, 359 FlowPackage.Literals.ARTIFACT__INBOUND_RELATIONSHIPS, 360 context, 361 progressMonitor); 362 363 ret.getContent().add(table); 364 return ret; 365 } 366 367 private Action createOutboundRelationshipsAction( 368 Action action, 369 org.nasdanika.html.emf.EObjectActionResolver.Context context, 370 ProgressMonitor progressMonitor) throws Exception { 371 Collection<ColumnBuilder<? super Map.Entry<String, Relationship>>> columnBuilders = new ArrayList<>(); 372 columnBuilders.add(new ColumnBuilder<Map.Entry<String, Relationship>>() { 373 374 @Override 375 public void buildHeader( 376 TableCell header, 377 Action base, 378 ETypedElement typedElement, 379 org.nasdanika.html.emf.EObjectActionResolver.Context context, 380 ProgressMonitor progressMonitor) 381 throws Exception { 382 header.getContent().add(createText("Key")); 383 } 384 385 @Override 386 public void buildCell( 387 Map.Entry<String, Relationship> rowElement, 388 TableCell cell, 389 Action base, 390 ETypedElement typedElement, 391 org.nasdanika.html.emf.EObjectActionResolver.Context context, 392 ProgressMonitor progressMonitor) 393 throws Exception { 394 EObject renderedValue = renderValue(base, typedElement, rowElement.getKey(), context, progressMonitor); 395 if (renderedValue != null) { 396 cell.getContent().add(renderedValue); 397 } 398 } 399 }); 400 401 columnBuilders.add(new ColumnBuilder<Map.Entry<String, Relationship>>() { 402 403 @Override 404 public void buildHeader( 405 TableCell header, 406 Action base, 407 ETypedElement typedElement, 408 org.nasdanika.html.emf.EObjectActionResolver.Context context, 409 ProgressMonitor progressMonitor) 410 throws Exception { 411 header.getContent().add(createText("Target")); 412 } 413 414 @Override 415 public void buildCell( 416 Map.Entry<String, Relationship> rowElement, 417 TableCell cell, 418 Action base, 419 ETypedElement typedElement, 420 org.nasdanika.html.emf.EObjectActionResolver.Context context, 421 ProgressMonitor progressMonitor) 422 throws Exception { 423 Relationship relationship = rowElement.getValue(); 424 EObject renderedValue = renderValue(base, typedElement, relationship.getTarget(), context, progressMonitor); 425 if (renderedValue != null) { 426 cell.getContent().add(renderedValue); 427 } 428 } 429 }); 430 431 columnBuilders.add(new ColumnBuilder<Map.Entry<String, Relationship>>() { 432 433 @Override 434 public void buildHeader( 435 TableCell header, 436 Action base, 437 ETypedElement typedElement, 438 org.nasdanika.html.emf.EObjectActionResolver.Context context, 439 ProgressMonitor progressMonitor) 440 throws Exception { 441 header.getContent().add(createText("Name")); 442 } 443 444 @Override 445 public void buildCell( 446 Map.Entry<String, Relationship> rowElement, 447 TableCell cell, 448 Action base, 449 ETypedElement typedElement, 450 org.nasdanika.html.emf.EObjectActionResolver.Context context, 451 ProgressMonitor progressMonitor) 452 throws Exception { 453 Relationship value = rowElement.getValue(); 454 EObject renderedValue = renderValue(base, typedElement, value.getName(), context, progressMonitor); 455 if (renderedValue != null) { 456 cell.getContent().add(renderedValue); 457 } 458 } 459 }); 460 461 columnBuilders.add(new ColumnBuilder<Map.Entry<String, Relationship>>() { 462 463 @Override 464 public void buildHeader( 465 TableCell header, 466 Action base, 467 ETypedElement typedElement, 468 org.nasdanika.html.emf.EObjectActionResolver.Context context, 469 ProgressMonitor progressMonitor) 470 throws Exception { 471 header.getContent().add(createText("Documentation")); 472 } 473 474 @Override 475 public void buildCell( 476 Map.Entry<String, Relationship> rowElement, 477 TableCell cell, 478 Action base, 479 ETypedElement typedElement, 480 org.nasdanika.html.emf.EObjectActionResolver.Context context, 481 ProgressMonitor progressMonitor) 482 throws Exception { 483 Relationship value = rowElement.getValue(); 484 EObject renderedValue = renderValue(base, typedElement, value.getDocumentation(), context, progressMonitor); 485 if (renderedValue != null) { 486 cell.getContent().add(renderedValue); 487 } 488 } 489 }); 490 491 Action ret = AppFactory.eINSTANCE.createAction(); 492 ret.setText("Outbound"); 493 494 Table table = buildTable( 495 getTarget().getOutboundRelationships(), 496 columnBuilders, 497 action, 498 FlowPackage.Literals.ARTIFACT__OUTBOUND_RELATIONSHIPS, 499 context, 500 progressMonitor); 501 502 ret.getContent().add(table); 503 return ret; 504 } 505 506 507}