001package org.nasdanika.html.model.app.graph.emf;
002
003import java.util.Collection;
004
005import org.eclipse.emf.common.util.URI;
006import org.eclipse.emf.ecore.EOperation;
007import org.eclipse.emf.ecore.EReference;
008import org.nasdanika.common.ProgressMonitor;
009import org.nasdanika.common.Supplier;
010import org.nasdanika.graph.emf.EOperationConnection;
011import org.nasdanika.graph.emf.EReferenceConnection;
012import org.nasdanika.graph.emf.QualifiedConnection;
013import org.nasdanika.graph.processor.ConnectionProcessorConfig;
014import org.nasdanika.html.model.app.Label;
015import org.nasdanika.html.model.app.Link;
016import org.nasdanika.html.model.app.graph.WidgetFactory;
017
018public class ConnectionProcessor {
019        
020        protected URI sourceURI;
021        protected URI targetURI;
022        protected ConnectionProcessorConfig<WidgetFactory, WidgetFactory> config;
023
024        public ConnectionProcessor(ConnectionProcessorConfig<WidgetFactory, WidgetFactory> config) {            
025                this.config = config;           
026                
027                config.getSourceEndpoint().thenAccept(se -> config.setTargetHandler(createTargetHandler(se)));
028                config.getTargetEndpoint().thenAccept(te -> config.setSourceHandler(createSourceHandler(te)));
029        }
030        
031        protected WidgetFactory createTargetHandler(WidgetFactory sourceEndpoint) {
032                return new WidgetFactory() {
033                        
034                        @Override
035                        public void resolve(URI base, ProgressMonitor progressMonitor) {
036                                targetURI = base;
037                        }
038                        
039                        private URI resolveBase(URI base) {
040                                if (base == null) {
041                                        return targetURI;
042                                }
043                                if (base.isRelative() && targetURI != null && !targetURI.isRelative()) {
044                                        return base.resolve(targetURI);                                         
045                                }
046                                return base;                            
047                        }
048                        
049                        @SuppressWarnings("unchecked")
050                        @Override
051                        public String createWidgetString(Object selector, URI base, ProgressMonitor progressMonitor) {
052                                if (selector instanceof Selector) {
053                                        return createWidget((Selector<String>) selector, base, progressMonitor);
054                                }
055                                return sourceEndpoint.createWidgetString(selector, resolveBase(base), progressMonitor);                                 
056                        }
057                        
058                        @Override
059                        public Object createWidget(Object selector, URI base, ProgressMonitor progressMonitor) {
060                                if (selector instanceof Selector) {
061                                        return createWidget((Selector<?>) selector, base, progressMonitor);
062                                }
063                                return sourceEndpoint.createWidget(selector, resolveBase(base), progressMonitor);
064                        }
065                                                
066                        @Override
067                        public <T> T createWidget(Selector<T> selector, URI base, ProgressMonitor progressMonitor) {
068                                if (selector instanceof ConnectionSelector) {
069                                        return selector.createWidget(this, resolveBase(base), progressMonitor);
070                                }
071                                return sourceEndpoint.createWidget(selector, resolveBase(base), progressMonitor);
072                        }       
073                        
074                        @Override
075                        public String createLinkString(URI base, ProgressMonitor progressMonitor) {
076                                return sourceEndpoint.createLinkString(resolveBase(base), progressMonitor);
077                        }
078                        
079                        @Override
080                        public Object createLink(URI base, ProgressMonitor progressMonitor) {
081                                return sourceEndpoint.createLink(resolveBase(base), progressMonitor);
082                        }
083                        
084                        @Override
085                        public Supplier<Collection<Label>> createLabelsSupplier() {
086                                return sourceEndpoint.createLabelsSupplier().then(labels -> {
087                                        for (Label label : labels) {
088                                                if (label instanceof Link) {
089                                                        ((Link) label).rebase(targetURI, sourceURI);
090                                                }
091                                        }
092                                        return labels;
093                                });
094                        }
095                        
096                        @Override
097                        public String createLabelString(ProgressMonitor progressMonitor) {
098                                return sourceEndpoint.createLabelString(progressMonitor);
099                        }
100                        
101                        @Override
102                        public Object createLabel(ProgressMonitor progressMonitor) {
103                                return sourceEndpoint.createLabel(progressMonitor);
104                        }
105                        
106                };
107                
108        }
109
110        protected WidgetFactory createSourceHandler(WidgetFactory targetEndpoint) {
111                return new WidgetFactory() {
112                        
113                        @Override
114                        public void resolve(URI base, ProgressMonitor progressMonitor) {
115                                sourceURI = base;                               
116                                QualifiedConnection<?> conn = (QualifiedConnection<?>) config.getElement();
117                                String path = conn.getPath();
118                                if (conn instanceof EReferenceConnection) {
119                                        EReference eRef = ((EReferenceConnection) conn).getReference();
120                                        if (eRef.isContainment()) {
121                                                String uriStr = "references/" + eRef.getName() + "/";
122                                                if (path != null) {
123                                                        uriStr += path + "/";
124                                                }
125                                                URI refURI = URI.createURI(uriStr);
126                                                targetEndpoint.resolve(refURI.resolve(base), progressMonitor);
127                                        }
128                                } else if (conn instanceof EOperationConnection) {
129                                        EOperation eOp = ((EOperationConnection) conn).getOperation();
130                                        String uriStr = "operations/" + eOp.getName() + "/";
131                                        if (path != null) {
132                                                uriStr += path + "/";
133                                        }
134                                        URI refURI = URI.createURI(uriStr);
135                                        targetEndpoint.resolve(refURI.resolve(base), progressMonitor);                                  
136                                }
137                        }
138                        
139                        private URI resolveBase(URI base) {
140                                if (base == null) {
141                                        return sourceURI;
142                                }
143                                if (base.isRelative() && sourceURI != null && !sourceURI.isRelative()) {
144                                        return base.resolve(sourceURI);                                         
145                                }
146                                return base;                            
147                        }
148                        
149                        @SuppressWarnings("unchecked")
150                        @Override
151                        public String createWidgetString(Object selector, URI base, ProgressMonitor progressMonitor) {
152                                if (selector instanceof Selector) {
153                                        return createWidget((Selector<String>) selector, base, progressMonitor);
154                                }
155                                return targetEndpoint.createWidgetString(selector, resolveBase(base), progressMonitor);
156                        }
157                        
158                        @Override
159                        public Object createWidget(Object selector, URI base, ProgressMonitor progressMonitor) {
160                                if (selector instanceof Selector) {
161                                        return createWidget((Selector<?>) selector, base, progressMonitor);
162                                }
163                                return targetEndpoint.createWidget(selector, resolveBase(base), progressMonitor); 
164                        }
165                        
166                        @Override
167                        public <T> T createWidget(Selector<T> selector, URI base, ProgressMonitor progressMonitor) {
168                                if (selector instanceof ConnectionSelector) {
169                                        return selector.createWidget(this, resolveBase(base), progressMonitor);
170                                }
171                                return targetEndpoint.createWidget(selector, resolveBase(base), progressMonitor);
172                        }       
173                        
174                        @Override
175                        public String createLinkString(URI base, ProgressMonitor progressMonitor) {
176                                return targetEndpoint.createLinkString(resolveBase(base), progressMonitor);
177                        }
178                        
179                        @Override
180                        public Object createLink(URI base, ProgressMonitor progressMonitor) {
181                                return targetEndpoint.createLink(resolveBase(base), progressMonitor);
182                        }
183                        
184                        @Override
185                        public Supplier<Collection<Label>> createLabelsSupplier() {
186                                return targetEndpoint.createLabelsSupplier().then(labels -> {
187                                        for (Label label : labels) {
188                                                if (label instanceof Link) {
189                                                        ((Link) label).rebase(targetURI, sourceURI);
190                                                }
191                                        }
192                                        return labels;
193                                });
194                        }
195                        
196                        @Override
197                        public String createLabelString(ProgressMonitor progressMonitor) {
198                                return targetEndpoint.createLabelString(progressMonitor);
199                        }
200                        
201                        @Override
202                        public Object createLabel(ProgressMonitor progressMonitor) {
203                                return targetEndpoint.createLabel(progressMonitor);
204                        }
205                        
206                };
207        }
208
209}