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         */
062        protected Function<T, T> createConfigureFunction(Context context) {
063                MapCompoundSupplierFactory<String,Object> attributesFactory = new MapCompoundSupplierFactory<>("Attributes");
064                for (Entry<String, EObject> ae: getTarget().getAttributes()) {
065                        EObject value = ae.getValue();
066                        attributesFactory.put(ae.getKey(), EObjectAdaptable.adaptToSupplierFactoryNonNull(value, Object.class, getRootAdapterFactory()));
067                }
068                
069                ListCompoundSupplierFactory<Object> contentFactory = new ListCompoundSupplierFactory<>("Content", EObjectAdaptable.adaptToSupplierFactoryNonNull(getContent(), Object.class));                          
070                
071                MapCompoundSupplierFactory<EStructuralFeature,Object> configurationFactory = new MapCompoundSupplierFactory<>("Attributes and Content");
072                configurationFactory.put(HtmlPackage.Literals.HTML_ELEMENT__ATTRIBUTES, attributesFactory);
073                configurationFactory.put(HtmlPackage.Literals.HTML_ELEMENT__CONTENT, contentFactory);
074                
075                FunctionFactory<BiSupplier<T, Map<EStructuralFeature, Object>>, T> applyAttributesAndContentFunctionFactory = HtmlElementAdapter::createApplyAttributesAndContentFunction;
076                FunctionFactory<T, BiSupplier<T, Map<EStructuralFeature, Object>>> configurationFunctionFactory = configurationFactory.asFunctionFactory();
077                return configurationFunctionFactory.then(applyAttributesAndContentFunctionFactory).create(context);
078        }
079
080        /**
081         * This implementation returns target content. Override to customize.
082         * @return
083         */
084        protected List<EObject> getContent() {
085                return getTarget().getContent();
086        }
087        
088        public static <T extends org.nasdanika.html.HTMLElement<?>> Function<BiSupplier<T, Map<EStructuralFeature, Object>>, T> createApplyAttributesAndContentFunction(Context context) {
089                return new Function<BiSupplier<T,Map<EStructuralFeature,Object>>, T>() {
090                        
091                        @Override
092                        public double size() {
093                                return 1;
094                        }
095                        
096                        @Override
097                        public String name() {
098                                return "Apply attributes";
099                        }
100                        
101                        @SuppressWarnings("unchecked")
102                        @Override
103                        public T execute(BiSupplier<T, Map<EStructuralFeature, Object>> input, ProgressMonitor progressMonitor) {
104                                T ret = input.getFirst();
105                                Map<EStructuralFeature, Object> config = input.getSecond();
106                                for (Entry<String, Object> ae: ((Map<String,Object>) config.get(HtmlPackage.Literals.HTML_ELEMENT__ATTRIBUTES)).entrySet()) {
107                                        ret.attribute(ae.getKey(), ae.getValue());
108                                }
109                                for (Object c: (List<Object>) config.get(HtmlPackage.Literals.HTML_ELEMENT__CONTENT)) {
110                                        if (ret instanceof Container) {
111                                                ((Container<?>) ret).content(c);
112                                        } else {
113                                                ret.getContent().add(c);
114                                        }
115                                }
116                                return ret;
117                        }
118                };
119                
120        }
121        
122        @SuppressWarnings("unchecked")
123        @Override
124        public M getTarget() {
125                return (M) super.getTarget();
126        }
127
128}