001: package org.drools.brms.client.packages;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.drools.brms.client.common.DirtyableComposite;
024: import org.drools.brms.client.common.ErrorPopup;
025: import org.drools.brms.client.common.FormStyleLayout;
026: import org.drools.brms.client.common.FormStylePopup;
027: import org.drools.brms.client.common.GenericCallback;
028: import org.drools.brms.client.common.InfoPopup;
029: import org.drools.brms.client.common.LoadingPopup;
030: import org.drools.brms.client.rpc.BuilderResult;
031: import org.drools.brms.client.rpc.PackageConfigData;
032: import org.drools.brms.client.rpc.RepositoryServiceFactory;
033: import org.drools.brms.client.rpc.SnapshotInfo;
034: import org.drools.brms.client.rulelist.EditItemEvent;
035:
036: import com.google.gwt.core.client.GWT;
037: import com.google.gwt.user.client.Command;
038: import com.google.gwt.user.client.DeferredCommand;
039: import com.google.gwt.user.client.Window;
040: import com.google.gwt.user.client.rpc.AsyncCallback;
041: import com.google.gwt.user.client.ui.Button;
042: import com.google.gwt.user.client.ui.ClickListener;
043: import com.google.gwt.user.client.ui.Composite;
044: import com.google.gwt.user.client.ui.FlexTable;
045: import com.google.gwt.user.client.ui.HTML;
046: import com.google.gwt.user.client.ui.HorizontalPanel;
047: import com.google.gwt.user.client.ui.Image;
048: import com.google.gwt.user.client.ui.KeyboardListener;
049: import com.google.gwt.user.client.ui.Label;
050: import com.google.gwt.user.client.ui.Panel;
051: import com.google.gwt.user.client.ui.RadioButton;
052: import com.google.gwt.user.client.ui.ScrollPanel;
053: import com.google.gwt.user.client.ui.SimplePanel;
054: import com.google.gwt.user.client.ui.TextArea;
055: import com.google.gwt.user.client.ui.TextBox;
056: import com.google.gwt.user.client.ui.VerticalPanel;
057: import com.google.gwt.user.client.ui.Widget;
058:
059: /**
060: * This is the widget for building packages, validating etc. Visually decorates
061: * or wraps a rule editor widget with buttons for this purpose.
062: *
063: * @author Michael Neale
064: */
065: public class PackageBuilderWidget extends Composite {
066:
067: public FormStyleLayout layout;
068: private PackageConfigData conf;
069: private EditItemEvent editEvent;
070:
071: public PackageBuilderWidget(final PackageConfigData conf,
072: EditItemEvent editEvent) {
073: layout = new FormStyleLayout("images/package_builder.png",
074: "Verify and assemble package");
075: this .conf = conf;
076: this .editEvent = editEvent;
077:
078: final SimplePanel buildResults = new SimplePanel();
079:
080: final TextBox selector = new TextBox();
081: final Button b = new Button("Build package");
082: b
083: .setTitle("This will validate and compile all the assets in a package.");
084: b.addClickListener(new ClickListener() {
085: public void onClick(Widget w) {
086: doBuild(buildResults, selector.getText());
087: }
088: });
089:
090: Button buildSource = new Button("Show package source");
091: buildSource.addClickListener(new ClickListener() {
092: public void onClick(Widget w) {
093: doBuildSource(conf.uuid, conf.name);
094: }
095: });
096: layout.addAttribute("View source for package", buildSource);
097:
098: HorizontalPanel buildStuff = new HorizontalPanel();
099: buildStuff.add(b);
100: buildStuff.add(new HTML(
101: " <i>(Optional) selector name: </i>"));
102: buildStuff.add(selector);
103: buildStuff
104: .add(new InfoPopup(
105: "Custom selector",
106: "A selector is configured by administrators to choose what assets form part of a package build. "
107: + "This is configured on the server side. The name given is the name of the configuration that the administrator has set."
108: + " This is an optional feature (if you don't know what it is, you probably don't need to use it)."));
109:
110: layout.addAttribute("Build binary package:", buildStuff);
111: layout
112: .addRow(new HTML(
113: "<i><small>Building a package will collect all the assets, validate and compile into a deployable package.</small></i>"));
114: layout.addRow(buildResults);
115:
116: layout.setStyleName("package-Editor");
117:
118: layout.setWidth("100%");
119:
120: initWidget(layout);
121: }
122:
123: /**
124: * Actually build the source, and display it.
125: */
126: public static void doBuildSource(final String uuid,
127: final String name) {
128: LoadingPopup.showMessage("Assembling package source...");
129: DeferredCommand.add(new Command() {
130: public void execute() {
131: RepositoryServiceFactory.getService()
132: .buildPackageSource(uuid,
133: new GenericCallback() {
134: public void onSuccess(Object data) {
135: String content = (String) data;
136: showSource(content, name);
137: }
138: });
139: }
140: });
141: }
142:
143: /**
144: * Popup the view source dialog, showing the given content.
145: */
146: public static void showSource(final String content, String name) {
147: FormStylePopup pop = new FormStylePopup(
148: "images/view_source.gif", "Viewing source for: " + name);
149: final TextArea area = new TextArea();
150: area.setVisibleLines(30);
151: area.setWidth("100%");
152: area.setCharacterWidth(80);
153: pop.addRow(area);
154: area.setText(content);
155: area.setEnabled(true);
156: area
157: .setTitle("THIS IS READ ONLY - you may copy and paste, but not edit.");
158:
159: area.addKeyboardListener(new KeyboardListener() {
160:
161: public void onKeyDown(Widget arg0, char arg1, int arg2) {
162: area.setText(content);
163: }
164:
165: public void onKeyPress(Widget arg0, char arg1, int arg2) {
166: area.setText(content);
167: }
168:
169: public void onKeyUp(Widget arg0, char arg1, int arg2) {
170: area.setText(content);
171: }
172:
173: });
174:
175: LoadingPopup.close();
176: pop.setPopupPosition((DirtyableComposite.getWidth() - pop
177: .getOffsetWidth()) / 2, 100);
178: pop.show();
179:
180: }
181:
182: /**
183: * Actually do the building.
184: *
185: * @param buildResults
186: * The panel to stuff the results in.
187: * @param selectorName
188: */
189: private void doBuild(final Panel buildResults,
190: final String selectorName) {
191:
192: buildResults.clear();
193:
194: final HorizontalPanel busy = new HorizontalPanel();
195: busy.add(new Label(
196: "Validating and building package, please wait..."));
197: busy.add(new Image("images/spinner.gif"));
198:
199: buildResults.add(busy);
200:
201: DeferredCommand.add(new Command() {
202: public void execute() {
203: RepositoryServiceFactory.getService().buildPackage(
204: conf.uuid, selectorName, new AsyncCallback() {
205: public void onSuccess(Object data) {
206: if (data == null) {
207: showSuccessfulBuild(buildResults);
208:
209: } else {
210: BuilderResult[] results = (BuilderResult[]) data;
211: showBuilderErrors(results,
212: buildResults);
213: }
214: }
215:
216: public void onFailure(Throwable t) {
217: ErrorPopup.showMessage(t.getMessage());
218: buildResults.clear();
219: }
220: });
221: }
222: });
223:
224: }
225:
226: /**
227: * This is called to display the success (and a download option).
228: *
229: * @param buildResults
230: */
231: private void showSuccessfulBuild(Panel buildResults) {
232: buildResults.clear();
233: VerticalPanel vert = new VerticalPanel();
234:
235: vert
236: .add(new HTML(
237: "<img src='images/tick_green.gif'/><i>Package built successfully.</i>"));
238: final String hyp = getDownloadLink(this .conf);
239:
240: HTML html = new HTML("<a href='" + hyp
241: + "' target='_blank'>Download binary package</a>");
242:
243: // Button download = new Button("Download binary package");
244: // download.setTitle( "You can download the package here for deployment,
245: // or you can use the snapshot deployment feature to have a more
246: // permanent downloadable package." );
247: // download.addClickListener( new ClickListener() {
248: // public void onClick(Widget arg0) {
249: // Window.open( hyp, "downloading...",
250: // "resizable=no,scrollbars=yes,status=no" );
251: // }
252: // });
253:
254: // vert.add( download );
255: vert.add(html);
256: Button snap = new Button("Create snapshot for deployment");
257: snap.addClickListener(new ClickListener() {
258: public void onClick(Widget w) {
259: showSnapshotDialog(w);
260: }
261: });
262: vert.add(snap);
263:
264: buildResults.add(vert);
265: }
266:
267: /**
268: * Get a download link for the binary package.
269: */
270: public static String getDownloadLink(PackageConfigData conf) {
271: String hurl = GWT.getModuleBaseURL() + "package/" + conf.name;
272: if (!conf.isSnapshot) {
273: hurl = hurl + "/" + PackageSnapshotView.LATEST_SNAPSHOT;
274: } else {
275: hurl = hurl + "/" + conf.snapshotName;
276: }
277: final String uri = hurl;
278: return uri;
279: }
280:
281: /**
282: * This is called in the unhappy event of there being errors.
283: */
284: private void showBuilderErrors(BuilderResult[] results,
285: Panel buildResults) {
286: buildResults.clear();
287:
288: FlexTable errTable = new FlexTable();
289: errTable.setStyleName("build-Results");
290: errTable.setText(0, 1, "Format");
291: errTable.setText(0, 2, "Name");
292: errTable.setText(0, 3, "Message");
293:
294: for (int i = 0; i < results.length; i++) {
295: int row = i + 1;
296: final BuilderResult res = results[i];
297: errTable.setWidget(row, 0, new Image("images/error.gif"));
298: errTable.setText(row, 1, res.assetFormat);
299: errTable.setText(row, 2, res.assetName);
300: errTable.setText(row, 3, res.message);
301:
302: if (!"package".equals(res.assetFormat)) {
303: Button show = new Button("Show");
304: show.addClickListener(new ClickListener() {
305: public void onClick(Widget w) {
306: editEvent.open(res.uuid);
307: }
308: });
309: errTable.setWidget(row, 4, show);
310: }
311: }
312:
313: errTable.setWidth("100%");
314: ScrollPanel scroll = new ScrollPanel(errTable);
315: scroll.setAlwaysShowScrollBars(true);
316: scroll.setSize("100%", "25em");
317:
318: buildResults.add(scroll);
319:
320: }
321:
322: /**
323: * This will display a dialog for creating a snapshot.
324: */
325: private void showSnapshotDialog(Widget w) {
326: LoadingPopup.showMessage("Loading existing snapshots...");
327: final FormStylePopup form = new FormStylePopup(
328: "images/snapshot.png",
329: "Create a snapshot for deployment.");
330: form
331: .addRow(new HTML(
332: "<i>A package snapshot is essentially a "
333: + "read only 'locked in' and labelled view of a package at a point in time, which can be used for deployment.</i>"));
334:
335: final VerticalPanel vert = new VerticalPanel();
336: form.addAttribute("Choose or create snapshot name:", vert);
337: final List radioList = new ArrayList();
338: final TextBox newName = new TextBox();
339: final String newSnapshotText = "NEW: ";
340:
341: RepositoryServiceFactory.getService().listSnapshots(conf.name,
342: new GenericCallback() {
343: public void onSuccess(Object data) {
344: SnapshotInfo[] result = (SnapshotInfo[]) data;
345: for (int i = 0; i < result.length; i++) {
346: RadioButton existing = new RadioButton(
347: "snapshotNameGroup", result[i].name);
348: radioList.add(existing);
349: vert.add(existing);
350: }
351: HorizontalPanel newSnap = new HorizontalPanel();
352:
353: final RadioButton newSnapRadio = new RadioButton(
354: "snapshotNameGroup", newSnapshotText);
355: newSnap.add(newSnapRadio);
356: newName.setEnabled(false);
357: newSnapRadio
358: .addClickListener(new ClickListener() {
359:
360: public void onClick(Widget w) {
361: newName.setEnabled(true);
362: }
363:
364: });
365:
366: newSnap.add(newName);
367: radioList.add(newSnapRadio);
368: vert.add(newSnap);
369:
370: LoadingPopup.close();
371: }
372: });
373:
374: final TextBox comment = new TextBox();
375: form.addAttribute("Comment:", comment);
376:
377: Button create = new Button("Create new snapshot");
378: form.addAttribute("", create);
379:
380: create.addClickListener(new ClickListener() {
381: String name = "";
382:
383: public void onClick(Widget w) {
384: boolean replace = false;
385: for (Iterator iter = radioList.iterator(); iter
386: .hasNext();) {
387: RadioButton but = (RadioButton) iter.next();
388: if (but.isChecked()) {
389: name = but.getText();
390: if (!but.getText().equals(newSnapshotText)) {
391: replace = true;
392: }
393: break;
394: }
395: }
396: if (name.equals(newSnapshotText)) {
397: name = newName.getText();
398: }
399:
400: if (name.equals("")) {
401: Window
402: .alert("You have to enter or chose a label (name) for the snapshot.");
403: return;
404: }
405:
406: RepositoryServiceFactory.getService()
407: .createPackageSnapshot(conf.name, name,
408: replace, comment.getText(),
409: new GenericCallback() {
410: public void onSuccess(Object data) {
411: Window
412: .alert("The snapshot called: "
413: + name
414: + " was successfully created.");
415: form.hide();
416: }
417: });
418: }
419: });
420:
421: form.setWidth("50%");
422:
423: form.setPopupPosition((DirtyableComposite.getWidth() - form
424: .getOffsetWidth()) / 2, 100);
425: form.show();
426:
427: // form.setPopupPosition( Window.getClientWidth() / 3,
428: // Window.getClientHeight() / 3 );
429: // form.show();
430:
431: }
432:
433: }
|