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}