001package org.nasdanika.html.flow;
002
003import java.util.Collections;
004import java.util.HashSet;
005import java.util.List;
006import java.util.Map;
007import java.util.Set;
008import java.util.function.BiConsumer;
009import java.util.function.Consumer;
010import java.util.stream.Collectors;
011
012import org.eclipse.emf.common.util.EList;
013import org.eclipse.emf.ecore.EClass;
014import org.eclipse.emf.ecore.EObject;
015import org.eclipse.emf.ecore.ETypedElement;
016import org.nasdanika.common.Context;
017import org.nasdanika.common.ProgressMonitor;
018import org.nasdanika.common.Util;
019import org.nasdanika.emf.EmfUtil;
020import org.nasdanika.flow.ArtifactParticipantResponsibility;
021import org.nasdanika.flow.FlowElement;
022import org.nasdanika.flow.FlowPackage;
023import org.nasdanika.flow.Participant;
024import org.nasdanika.flow.ParticipantResponsibility;
025import org.nasdanika.html.model.app.Action;
026import org.nasdanika.html.model.app.AppFactory;
027import org.nasdanika.html.model.app.SectionStyle;
028import org.nasdanika.html.model.bootstrap.BootstrapFactory;
029import org.nasdanika.html.model.bootstrap.Table;
030import org.nasdanika.html.model.bootstrap.TableCell;
031import org.nasdanika.html.model.bootstrap.TableHeader;
032import org.nasdanika.html.model.bootstrap.TableRow;
033import org.nasdanika.html.model.bootstrap.TableSection;
034import org.nasdanika.ncore.util.NamedElementComparator;
035
036public class ParticipantActionBuilder extends ServiceProviderActionBuilder<Participant> {
037        
038        public ParticipantActionBuilder(Participant 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 (Participant 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.PARTICIPANT__ARTIFACTS);
062                properties.add(FlowPackage.Literals.PARTICIPANT__PARTICIPATES);
063                properties.add(FlowPackage.Literals.PARTICIPANT__RESOURCES);
064                properties.add(FlowPackage.Literals.PARTICIPANT__BASES);
065                properties.add(FlowPackage.Literals.PARTICIPANT__SPECIALIZATIONS);
066                return properties;
067        }
068        
069        @Override
070        protected void resolve(
071                        Action action, 
072                        org.nasdanika.html.emf.EObjectActionResolver.Context context,
073                        ProgressMonitor progressMonitor) throws Exception {
074                super.resolve(action, context, progressMonitor);
075                
076                // Responsibilities
077                EList<Action> sections = action.getSections();
078                
079                Set<EClass> groupKeys = new HashSet<>(); // For sections                
080
081                Map<EClass, List<ParticipantResponsibility<?>>> responsibleGroup = Util.groupBy(getTarget().getResponsible(), EObject::eClass);
082                groupKeys.addAll(responsibleGroup.keySet());
083
084                Map<EClass, List<ParticipantResponsibility<?>>> accountableGroup = Util.groupBy(getTarget().getAccountable(), EObject::eClass);
085                groupKeys.addAll(accountableGroup.keySet());
086
087                Map<EClass, List<ParticipantResponsibility<?>>> consultedGroup = Util.groupBy(getTarget().getConsulted(), EObject::eClass);
088                groupKeys.addAll(consultedGroup.keySet());
089
090                Map<EClass, List<ParticipantResponsibility<?>>> informedGroup = Util.groupBy(getTarget().getInformed(), EObject::eClass);
091                groupKeys.addAll(informedGroup.keySet());
092                
093                if (!groupKeys.isEmpty()) {
094                        Action responsibilitiesAction = AppFactory.eINSTANCE.createAction();                    
095                        responsibilitiesAction.setText("Responsible");
096                        responsibilitiesAction.setSectionStyle(SectionStyle.HEADER);
097                        sections.add(responsibilitiesAction);
098                        EList<Action> rSections = responsibilitiesAction.getSections();
099                        for (EClass groupKey: groupKeys.stream().sorted(EmfUtil.ENAMED_ELEMENT_COMPARATOR).collect(Collectors.toList())) {
100                                rSections.add(createResponsivilityGroupAction(
101                                                groupKey,
102                                                responsibleGroup.get(groupKey),
103                                                accountableGroup.get(groupKey),
104                                                consultedGroup.get(groupKey),
105                                                informedGroup.get(groupKey),
106                                                action,
107                                                context, 
108                                                progressMonitor));                      
109                        }
110                }
111                
112        }
113
114        private Action createResponsivilityGroupAction(
115                        EClass typeKey, 
116                        List<ParticipantResponsibility<?>> responsible,
117                        List<ParticipantResponsibility<?>> accountable, 
118                        List<ParticipantResponsibility<?>> consulted,
119                        List<ParticipantResponsibility<?>> informed, 
120                        Action base,
121                        org.nasdanika.html.emf.EObjectActionResolver.Context context,
122                        ProgressMonitor progressMonitor) throws Exception {
123
124                Action groupAction = AppFactory.eINSTANCE.createAction();                       
125                String groupName = typeKey.getName();
126                if ("Activity".equals(groupName)) {
127                        groupAction.setText("Activities");
128                } else {
129                        groupAction.setText(groupName + "s");
130                }
131                
132                if (typeKey == FlowPackage.Literals.ARTIFACT_PARTICIPANT_RESPONSIBILITY) {
133                        groupAction.setText("Activity artifacts");
134                        Table responsibilitiesTable = BootstrapFactory.eINSTANCE.createTable();
135                        TableHeader header = BootstrapFactory.eINSTANCE.createTableHeader();
136                        responsibilitiesTable.setHeader(header);
137                        TableRow headerRow = BootstrapFactory.eINSTANCE.createTableRow();
138                        header.getRows().add(headerRow);
139                        EList<TableCell> headerRowCells = headerRow.getCells();
140                        for (String title: new String[] {"Activity", "Responsible", "Accountable", "Consulted", "Informed"}) {
141                                TableCell headerCell = BootstrapFactory.eINSTANCE.createTableCell();
142                                headerCell.setHeader(true);
143                                headerRowCells.add(headerCell);
144                                headerCell.getContent().add(createText(title));
145                        }
146                        
147                        // Group all by container. Sort containers For each container create a row
148                        Set<EObject> flowElements = new HashSet<>(); // For sections            
149
150                        Map<EObject, List<ParticipantResponsibility<?>>> responsibleGroup = responsible == null ? Collections.emptyMap() : Util.groupBy(responsible, EObject::eContainer);
151                        flowElements.addAll(responsibleGroup.keySet());
152
153                        Map<EObject, List<ParticipantResponsibility<?>>> accountableGroup = accountable == null ? Collections.emptyMap() : Util.groupBy(accountable, EObject::eContainer);
154                        flowElements.addAll(accountableGroup.keySet());
155
156                        Map<EObject, List<ParticipantResponsibility<?>>> consultedGroup = consulted == null ? Collections.emptyMap() : Util.groupBy(consulted, EObject::eContainer);
157                        flowElements.addAll(consultedGroup.keySet());
158
159                        Map<EObject, List<ParticipantResponsibility<?>>> informedGroup = informed == null ? Collections.emptyMap() : Util.groupBy(informed, EObject::eContainer);
160                        flowElements.addAll(informedGroup.keySet());
161
162                        TableSection body = BootstrapFactory.eINSTANCE.createTableSection();
163                        responsibilitiesTable.setBody(body);
164                        EList<TableRow> bodyRows = body.getRows();
165                        
166                        for (FlowElement<?> container: flowElements.stream().map(e -> (FlowElement<?>) e).sorted(FlowActionBuilder::compareFlowElements).collect(Collectors.toList())) {
167                                TableRow containerRow = BootstrapFactory.eINSTANCE.createTableRow();
168                                bodyRows.add(containerRow);
169
170                                TableCell containerCell = BootstrapFactory.eINSTANCE.createTableCell();
171                                containerRow.getCells().add(containerCell);
172                                containerCell.getContent().add(renderValue(base, null, container, context, progressMonitor));
173                                
174                                TableCell responsibleCell = BootstrapFactory.eINSTANCE.createTableCell();
175                                containerRow.getCells().add(responsibleCell);
176                                List<ParticipantResponsibility<?>> containerResponsible = responsibleGroup.get(container);
177                                if (containerResponsible != null) {
178                                        buildResponsibilityCell(containerResponsible.stream().map(e -> ((ArtifactParticipantResponsibility) e).getArtifact()).sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList()), responsibleCell, base, context, progressMonitor);
179                                }
180                                
181                                TableCell accountableCell = BootstrapFactory.eINSTANCE.createTableCell();
182                                containerRow.getCells().add(accountableCell);
183                                List<ParticipantResponsibility<?>> containerAccountable = accountableGroup.get(container);
184                                if (containerAccountable != null) {
185                                        buildResponsibilityCell(containerAccountable.stream().map(e -> ((ArtifactParticipantResponsibility) e).getArtifact()).sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList()), accountableCell, base, context, progressMonitor);
186                                }
187                                
188                                TableCell consultedCell = BootstrapFactory.eINSTANCE.createTableCell();
189                                containerRow.getCells().add(consultedCell);
190                                List<ParticipantResponsibility<?>> containerConsulted = consultedGroup.get(container);
191                                if (containerConsulted != null) {
192                                        buildResponsibilityCell(containerConsulted.stream().map(e -> ((ArtifactParticipantResponsibility) e).getArtifact()).sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList()), consultedCell, base, context, progressMonitor);
193                                }
194                                
195                                TableCell informedCell = BootstrapFactory.eINSTANCE.createTableCell();
196                                containerRow.getCells().add(informedCell);
197                                List<ParticipantResponsibility<?>> containerInformed = informedGroup.get(container);
198                                if (containerInformed != null) {
199                                        buildResponsibilityCell(containerInformed.stream().map(e -> ((ArtifactParticipantResponsibility) e).getArtifact()).sorted(NamedElementComparator.INSTANCE).collect(Collectors.toList()), informedCell, base, context, progressMonitor);
200                                }
201                                
202                        }
203                        
204                        groupAction.getContent().add(responsibilitiesTable);
205                } else {
206                        Table responsibilitiesTable = BootstrapFactory.eINSTANCE.createTable();
207                        TableHeader header = BootstrapFactory.eINSTANCE.createTableHeader();
208                        responsibilitiesTable.setHeader(header);
209                        TableRow headerRow = BootstrapFactory.eINSTANCE.createTableRow();
210                        header.getRows().add(headerRow);
211                        EList<TableCell> headerRowCells = headerRow.getCells();
212                        for (String title: new String[] {"Responsible", "Accountable", "Consulted", "Informed"}) {
213                                TableCell headerCell = BootstrapFactory.eINSTANCE.createTableCell();
214                                headerCell.setHeader(true);
215                                headerRowCells.add(headerCell);
216                                headerCell.getContent().add(createText(title));
217                        }
218                        
219                        TableSection body = BootstrapFactory.eINSTANCE.createTableSection();
220                        responsibilitiesTable.setBody(body);
221                        EList<TableRow> bodyRows = body.getRows();
222                        
223                        TableRow responsibilitiesRow = BootstrapFactory.eINSTANCE.createTableRow();
224                        bodyRows.add(responsibilitiesRow);
225                        
226                        TableCell responsibleCell = BootstrapFactory.eINSTANCE.createTableCell();
227                        responsibilitiesRow.getCells().add(responsibleCell);
228                        buildResponsibilityCell(responsible, responsibleCell, base, context, progressMonitor);
229                        
230                        TableCell accountableCell = BootstrapFactory.eINSTANCE.createTableCell();
231                        responsibilitiesRow.getCells().add(accountableCell);
232                        buildResponsibilityCell(accountable, accountableCell, base, context, progressMonitor);
233                        
234                        TableCell consultedCell = BootstrapFactory.eINSTANCE.createTableCell();
235                        responsibilitiesRow.getCells().add(consultedCell);
236                        buildResponsibilityCell(consulted, consultedCell, base, context, progressMonitor);
237                        
238                        TableCell informedCell = BootstrapFactory.eINSTANCE.createTableCell();
239                        responsibilitiesRow.getCells().add(informedCell);
240                        buildResponsibilityCell(informed, informedCell, base, context, progressMonitor);
241                        
242                        groupAction.getContent().add(responsibilitiesTable);
243                }
244                
245                return groupAction;
246        }
247        
248        private void buildResponsibilityCell(
249                        List<ParticipantResponsibility<?>> elements,                    
250                        TableCell cell,
251                        Action base,
252                        org.nasdanika.html.emf.EObjectActionResolver.Context context,
253                        ProgressMonitor progressMonitor) throws Exception {
254                
255                if (elements != null && !elements.isEmpty()) {
256                        cell.getContent().add(renderValue(base, null, elements, context, progressMonitor));
257                }
258                        
259        }
260
261}