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 * [email protected]::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 * [email protected]::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 }