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}