001package org.nasdanika.html.model.html.gen;
002
003import java.util.List;
004import java.util.Map;
005import java.util.Map.Entry;
006
007import org.eclipse.emf.common.notify.Adapter;
008import org.eclipse.emf.common.notify.AdapterFactory;
009import org.eclipse.emf.common.notify.impl.AdapterImpl;
010import org.eclipse.emf.ecore.EObject;
011import org.eclipse.emf.ecore.EStructuralFeature;
012import org.eclipse.emf.ecore.util.EcoreUtil;
013import org.nasdanika.common.BiSupplier;
014import org.nasdanika.common.Context;
015import org.nasdanika.common.Function;
016import org.nasdanika.common.FunctionFactory;
017import org.nasdanika.common.ListCompoundSupplierFactory;
018import org.nasdanika.common.MapCompoundSupplierFactory;
019import org.nasdanika.common.ProgressMonitor;
020import org.nasdanika.emf.ComposeableAdapterFactory;
021import org.nasdanika.emf.EObjectAdaptable;
022import org.nasdanika.html.Container;
023import org.nasdanika.html.model.html.HtmlPackage;
024
025/**
026 * Base class for HTML Element adapters providing common functionality
027 * @author Pavel
028 *
029 * @param <M>
030 * @param <T>
031 */
032public abstract class HtmlElementAdapter<M extends org.nasdanika.html.model.html.HtmlElement, T extends org.nasdanika.html.HTMLElement<?>> extends AdapterImpl {
033        
034        protected AdapterFactory adapterFactory;
035        
036        protected AdapterFactory getRootAdapterFactory() {
037                return adapterFactory instanceof ComposeableAdapterFactory ? ((ComposeableAdapterFactory) adapterFactory).getRootAdapterFactory() : adapterFactory;
038        }
039        
040        protected HtmlElementAdapter(M htmlElement, AdapterFactory adapterFactory) {
041                setTarget(htmlElement);
042                this.adapterFactory = adapterFactory;
043        }
044        
045        protected Adapter getRegisteredAdapter(EObject eObject, Object type) {
046                Adapter result = EcoreUtil.getExistingAdapter(eObject, type);
047                if (result != null) {
048                        return result;
049                }
050
051                AdapterFactory factory = getRootAdapterFactory();
052                return factory == null ? null : factory.adaptNew(eObject, type);
053        }       
054        
055        /**
056         * Creates a function which configures the element and returns it.
057         * This implementation applies attributes and adds content. Override to implement additional configuration.
058         * You may chain configuration functions with <code>.then</code>
059         * @param context
060         * @return
061         * @throws Exception
062         */
063        protected Function<T, T> createConfigureFunction(Context context) throws Exception {
064                MapCompoundSupplierFactory<String,Object> attributesFactory = new MapCompoundSupplierFactory<>("Attributes");
065                for (Entry<String, EObject> ae: getTarget().getAttributes()) {
066                        EObject value = ae.getValue();
067                        attributesFactory.put(ae.getKey(), EObjectAdaptable.adaptToSupplierFactoryNonNull(value, Object.class, getRootAdapterFactory()));
068                }
069                
070                ListCompoundSupplierFactory<Object> contentFactory = new ListCompoundSupplierFactory<>("Content", EObjectAdaptable.adaptToSupplierFactoryNonNull(getContent(), Object.class));                          
071                
072                MapCompoundSupplierFactory<EStructuralFeature,Object> configurationFactory = new MapCompoundSupplierFactory<>("Attributes and Content");
073                configurationFactory.put(HtmlPackage.Literals.HTML_ELEMENT__ATTRIBUTES, attributesFactory);
074                configurationFactory.put(HtmlPackage.Literals.HTML_ELEMENT__CONTENT, contentFactory);
075                
076                FunctionFactory<BiSupplier<T, Map<EStructuralFeature, Object>>, T> applyAttributesAndContentFunctionFactory = HtmlElementAdapter::createApplyAttributesAndContentFunction;
077                FunctionFactory<T, BiSupplier<T, Map<EStructuralFeature, Object>>> configurationFunctionFactory = configurationFactory.asFunctionFactory();
078                return configurationFunctionFactory.then(applyAttributesAndContentFunctionFactory).create(context);
079        }
080
081        /**
082         * This implementation returns target content. Override to customize.
083         * @return
084         */
085        protected List<EObject> getContent() {
086                return getTarget().getContent();
087        }
088        
089        public static <T extends org.nasdanika.html.HTMLElement<?>> Function<BiSupplier<T, Map<EStructuralFeature, Object>>, T> createApplyAttributesAndContentFunction(Context context) {
090                return new Function<BiSupplier<T,Map<EStructuralFeature,Object>>, T>() {
091                        
092                        @Override
093                        public double size() {
094                                return 1;
095                        }
096                        
097                        @Override
098                        public String name() {
099                                return "Apply attributes";
100                        }
101                        
102                        @SuppressWarnings("unchecked")
103                        @Override
104                        public T execute(BiSupplier<T, Map<EStructuralFeature, Object>> input, ProgressMonitor progressMonitor) throws Exception {
105                                T ret = input.getFirst();
106                                Map<EStructuralFeature, Object> config = input.getSecond();
107                                for (Entry<String, Object> ae: ((Map<String,Object>) config.get(HtmlPackage.Literals.HTML_ELEMENT__ATTRIBUTES)).entrySet()) {
108                                        ret.attribute(ae.getKey(), ae.getValue());
109                                }
110                                for (Object c: (List<Object>) config.get(HtmlPackage.Literals.HTML_ELEMENT__CONTENT)) {
111                                        if (ret instanceof Container) {
112                                                ((Container<?>) ret).content(c);
113                                        } else {
114                                                ret.getContent().add(c);
115                                        }
116                                }
117                                return ret;
118                        }
119                };
120                
121        }
122        
123        @SuppressWarnings("unchecked")
124        @Override
125        public M getTarget() {
126                return (M) super.getTarget();
127        }
128
129}