001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.api.web.gwt.client; 021 022 import com.google.gwt.core.client.EntryPoint; 023 import com.google.gwt.core.client.JavaScriptObject; 024 import com.google.gwt.user.client.ui.FlowPanel; 025 import com.google.gwt.user.client.ui.Panel; 026 import com.google.gwt.user.client.ui.RootPanel; 027 import com.google.gwt.user.client.ui.Widget; 028 import org.sonar.api.web.gwt.client.webservices.*; 029 030 import java.util.Arrays; 031 032 public abstract class AbstractViewer implements EntryPoint { 033 034 public static final String HTML_ROOT_ID = "resource_viewers"; 035 036 private Resource resource; 037 private String renderedResourceKey = ""; 038 private Panel widgetPanel = null; 039 private boolean standAloneMode = true; 040 041 public void onModuleLoad() { 042 exportJavascript(); 043 } 044 045 /** 046 * Export GWT javascript methods to load and control the plugin, must export currently 2 method : 047 * I.E for plugin GWT id : foo.bar.MyPlugin, class foo.bar.client.MyPlugin : 048 * <p/> 049 * $wnd.load_foo_bar_MyPlugin = function() { 050 * called to the plugin init from JS 051 * obj.@foo.bar.client.MyPlugin::loadContainer()(); 052 * } 053 * $wnd.on_resource_loaded_foo_bar_MyPlugin = function() { 054 * called when a resource JSON object has been refreshed within the page 055 * obj.@foo.bar.client.MyPlugin::onResourceLoaded()(); 056 * } 057 */ 058 protected abstract void exportJavascript(); 059 060 /** 061 * When multiple widgets are bound to the same HTML div, this method will indicate 062 * If the resource widget is the default one to show when the widget is initialized 063 * 064 * @param metric the metric for which the widget is shown, cannot be null 065 * @param resource the resource bound to the widget 066 * @return true or false 067 */ 068 protected abstract boolean isDefault(WSMetrics.Metric metric, Resource resource); 069 070 /** 071 * Finds if a given metric is in the provided metrics list 072 * 073 * @param metric the metric to search 074 * @param metricsList the metric list 075 * @return true or false if not found 076 */ 077 protected boolean isMetricInList(WSMetrics.Metric metric, WSMetrics.Metric... metricsList) { 078 return Arrays.asList(metricsList).contains(metric); 079 } 080 081 /** 082 * When multiple widgets are in the same page, this method will indicate if the widget 083 * can be shown for the given resource 084 * 085 * @param resource the resource bound to the page 086 * @return true or false 087 */ 088 protected abstract boolean isForResource(Resource resource); 089 090 091 public Resource getResource() { 092 return resource; 093 } 094 095 private Resource loadResource() { 096 JavaScriptObject resourceJson = getResourceJSONObject(); 097 if (resourceJson != null) { 098 Resource resourceLoaded = ResourcesQuery.parseResources(resourceJson).get(0); 099 String currentMetricKey = ResourceDictionary.getViewerMetricKey(); 100 Boolean isDefaultForMetric = false; 101 if (currentMetricKey != null) { 102 isDefaultForMetric = isDefault(WSMetrics.get(currentMetricKey), resourceLoaded); 103 } 104 exportJSBooleanVariable("is_default_for_metric", Utils.widgetGWTIdJSEncode(getGwtId()), isDefaultForMetric); 105 exportJSBooleanVariable("is_for_resource", Utils.widgetGWTIdJSEncode(getGwtId()), isForResource(resourceLoaded)); 106 return resourceLoaded; 107 } 108 return null; 109 } 110 111 /** 112 * Called when a resource JSON object has been loaded within the page 113 */ 114 public final void onResourceLoaded() { 115 resource = loadResource(); 116 standAloneMode = false; 117 } 118 119 /** 120 * Called to render the widget for the given resource object loaded via the onResourceLoaded() method call 121 */ 122 public final void loadContainer() { 123 String resourceKey = ResourceDictionary.getViewerResourceKey(); 124 if (resourceKey != null) { 125 if (!standAloneMode && resource == null) { 126 Utils.showError("Unable to find JSON resource object, unable to render widget"); 127 return; 128 } else if (standAloneMode && resource == null) { 129 getResourceJsonObject(resourceKey); 130 return; 131 } 132 String currentResourceKey = isANumber(resourceKey) ? resource.getId().toString() : resource.getKey(); 133 if (!renderedResourceKey.equals(currentResourceKey)) { 134 // resource key has changed reload if not in standalone mode 135 if (!standAloneMode) { 136 resource = loadResource(); 137 } 138 139 if (widgetPanel == null) { 140 RootPanel rootPanel = RootPanel.get(HTML_ROOT_ID); 141 if (rootPanel == null) { 142 Utils.showError("Unable to find root panel " + HTML_ROOT_ID + " in page"); 143 } 144 widgetPanel = new FlowPanel(); 145 widgetPanel.setStyleName("gwt-ResourceTab"); 146 String panelId = "tab-" + Utils.widgetGWTIdJSEncode(getGwtId()); 147 widgetPanel.getElement().setId(panelId); 148 registerTab(panelId); 149 widgetPanel.setVisible(false); 150 rootPanel.add(widgetPanel); 151 } 152 153 renderedResourceKey = resourceKey; 154 155 if (widgetPanel != null) { 156 widgetPanel.clear(); 157 widgetPanel.add(render(resource)); 158 } 159 } 160 } 161 162 if (widgetPanel != null) { 163 widgetPanel.setVisible(true); 164 } 165 } 166 167 private static native void registerTab(Object tabId) /*-{ 168 $wnd.registeredTabs.push(tabId); 169 }-*/; 170 171 172 private native void exportJSBooleanVariable(String varPrefix, String encodedGWTId, boolean value)/*-{ 173 $wnd.config[varPrefix + "_" + encodedGWTId] = value; 174 }-*/; 175 176 /** 177 * Return the GWT id of the widget 178 */ 179 protected abstract String getGwtId(); 180 181 /** 182 * Renders the widget for the current resource 183 */ 184 protected abstract Widget render(Resource resource); 185 186 /** 187 * Return a JavaScriptObject object containing all the measure available for the current resource key 188 * 189 * @return the JavaScriptObject instance, should never be null 190 */ 191 protected native JavaScriptObject getResourceJSONObject()/*-{ 192 return $wnd.config['current_resource']; 193 }-*/; 194 195 196 private boolean isANumber(String resourceKey) { 197 boolean isIdResourceKey = true; 198 try { 199 Integer.parseInt(resourceKey); 200 } catch (NumberFormatException ex) { 201 isIdResourceKey = false; 202 } 203 return isIdResourceKey; 204 } 205 206 private void getResourceJsonObject(String resourceKey) { 207 ResourcesQuery.get(resourceKey).execute(new StandAloneResourceHandler()); 208 } 209 210 public class StandAloneResourceHandler extends BaseQueryCallback<Resources> { 211 public void onResponse(Resources resources, JavaScriptObject jsonResponse) { 212 resource = resources.firstResource(); 213 loadContainer(); 214 } 215 } 216 }