001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.contenteditor.widgetregistry.client; 029 030import org.opencms.acacia.client.I_CmsEntityRenderer; 031import org.opencms.acacia.client.I_CmsWidgetFactory; 032import org.opencms.ade.contenteditor.shared.CmsExternalWidgetConfiguration; 033import org.opencms.gwt.client.util.CmsDomUtil; 034 035import java.util.Collection; 036import java.util.HashMap; 037import java.util.HashSet; 038import java.util.Iterator; 039import java.util.List; 040import java.util.Map; 041import java.util.Set; 042 043import com.google.gwt.core.client.Scheduler; 044import com.google.gwt.core.client.Scheduler.RepeatingCommand; 045import com.google.gwt.user.client.Command; 046 047/** 048 * The widget registry.<p> 049 */ 050public final class WidgetRegistry { 051 052 /** The register widget function name. */ 053 public static final String REGISTER_WIDGET_FACTORY_FUNCTION = "registerWidgetFactory"; 054 055 /** The widget registry instance. */ 056 private static WidgetRegistry INSTANCE; 057 058 /** Map of registered renderers by name. */ 059 private Map<String, I_CmsEntityRenderer> m_renderers = new HashMap<String, I_CmsEntityRenderer>(); 060 061 /** The widget registry. */ 062 private Map<String, I_CmsWidgetFactory> m_widgetRegistry; 063 064 /** 065 * Constructor.<p> 066 */ 067 private WidgetRegistry() { 068 069 m_widgetRegistry = new HashMap<String, I_CmsWidgetFactory>(); 070 exportWidgetRegistration(); 071 } 072 073 /** 074 * Returns the widget registry instance.<p> 075 * 076 * @return the widget registry instance 077 */ 078 public static WidgetRegistry getInstance() { 079 080 if (INSTANCE == null) { 081 INSTANCE = new WidgetRegistry(); 082 } 083 return INSTANCE; 084 } 085 086 /** 087 * Adds a renderer which should be used by the Acacia editor.<p> 088 * 089 * @param renderer the renderer to add 090 */ 091 public void addRenderer(I_CmsEntityRenderer renderer) { 092 093 m_renderers.put(renderer.getName(), renderer); 094 } 095 096 /** 097 * Returns the registered renderers.<p> 098 * 099 * @return the renderers 100 */ 101 public Collection<I_CmsEntityRenderer> getRenderers() { 102 103 return m_renderers.values(); 104 } 105 106 /** 107 * Returns the registered widget factories.<p> 108 * 109 * @return the registered widget factories 110 */ 111 public Map<String, I_CmsWidgetFactory> getWidgetFactories() { 112 113 return m_widgetRegistry; 114 } 115 116 /** 117 * Registers external widgets.<p> 118 * 119 * @param externalWidgetConfigurations the external widget configurations 120 * @param callback the callback to execute when done 121 */ 122 public void registerExternalWidgets( 123 List<CmsExternalWidgetConfiguration> externalWidgetConfigurations, 124 final Command callback) { 125 126 final Set<String> initCalls = new HashSet<String>(); 127 for (CmsExternalWidgetConfiguration widgetConfiguration : externalWidgetConfigurations) { 128 if (!m_widgetRegistry.containsKey(widgetConfiguration.getWidgetName())) { 129 for (String cssResource : widgetConfiguration.getCssResourceLinks()) { 130 CmsDomUtil.ensureStyleSheetIncluded(cssResource); 131 } 132 for (String javaScriptResource : widgetConfiguration.getJavaScriptResourceLinks()) { 133 CmsDomUtil.ensureJavaScriptIncluded(javaScriptResource); 134 } 135 String initCall = widgetConfiguration.getInitCall(); 136 if (initCall != null) { 137 initCalls.add(initCall); 138 } 139 } 140 } 141 if (initCalls.isEmpty()) { 142 callback.execute(); 143 } else { 144 Scheduler.get().scheduleFixedDelay(new RepeatingCommand() { 145 146 /** The number of repeats. */ 147 private int m_repeats; 148 149 /** 150 * @see com.google.gwt.core.client.Scheduler.RepeatingCommand#execute() 151 */ 152 public boolean execute() { 153 154 m_repeats++; 155 Iterator<String> it = initCalls.iterator(); 156 while (it.hasNext()) { 157 String initCall = it.next(); 158 if (tryInitCall(initCall)) { 159 it.remove(); 160 } 161 } 162 if (initCalls.isEmpty()) { 163 callback.execute(); 164 return false; 165 } else { 166 if (m_repeats < 100) { 167 return true; 168 } else { 169 showInitCallError(initCalls); 170 return false; 171 } 172 } 173 174 } 175 }, 50); 176 } 177 } 178 179 /** 180 * Registers a widget.<p> 181 * 182 * @param widgetName the widget name 183 * @param widgetFactory the widget 184 */ 185 public void registerWidgetFactory(String widgetName, I_CmsWidgetFactory widgetFactory) { 186 187 m_widgetRegistry.put(widgetName, widgetFactory); 188 } 189 190 /** 191 * Logs an error.<p> 192 * 193 * @param error the error to log 194 */ 195 protected native void showError(String error) /*-{ 196 if ($wnd.console) { 197 $wnd.console.log(error); 198 } 199 throw error; 200 }-*/; 201 202 /** 203 * Logs an error for missing init calls.<p> 204 * 205 * @param initCalls the set of missing init calls 206 */ 207 protected void showInitCallError(Set<String> initCalls) { 208 209 StringBuffer buffer = new StringBuffer(); 210 buffer.append("init call(s) not found: "); 211 for (String init : initCalls) { 212 buffer.append(init); 213 buffer.append(" "); 214 } 215 showError(buffer.toString()); 216 } 217 218 /** 219 * Tries to initializes a widget with the given initialization call. Returns false if the init method was not available within the window context yet.<p> 220 * 221 * @param initCall the initialization function name 222 * 223 * @return <code>true</code> if the initialization function was available and has been executed 224 */ 225 protected native boolean tryInitCall(String initCall)/*-{ 226 try { 227 if ($wnd[initCall]) { 228 $wnd[initCall](); 229 return true; 230 } 231 } catch (error) { 232 throw "Failed excuting " + initCall 233 + " to initialize editing widget. \n" + error 234 } 235 return false; 236 }-*/; 237 238 /** 239 * Exports the widget registration.<p> 240 */ 241 private native void exportWidgetRegistration() /*-{ 242 var self = this; 243 $wnd[@org.opencms.ade.contenteditor.widgetregistry.client.WidgetRegistry::REGISTER_WIDGET_FACTORY_FUNCTION] = function( 244 factory) { 245 self.@org.opencms.ade.contenteditor.widgetregistry.client.WidgetRegistry::registerWrapper(Lorg/opencms/ade/contenteditor/widgetregistry/client/WidgetFactoryWrapper;)(factory); 246 } 247 }-*/; 248 249 /** 250 * Registers a widget wrapper as widget.<p> 251 * 252 * @param wrapper the wrapper object 253 */ 254 private void registerWrapper(WidgetFactoryWrapper wrapper) { 255 256 registerWidgetFactory(wrapper.getName(), wrapper); 257 } 258}