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}