001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package org.pentaho.designstudio.editors.actionsequence.wizards;
014:
015: import java.io.ByteArrayInputStream;
016: import java.io.File;
017: import java.io.InputStream;
018: import java.net.URI;
019: import java.net.URL;
020: import java.util.ArrayList;
021: import java.util.Collections;
022: import java.util.Comparator;
023: import java.util.Enumeration;
024: import java.util.List;
025:
026: import org.dom4j.Document;
027: import org.eclipse.core.resources.IContainer;
028: import org.eclipse.core.resources.IResource;
029: import org.eclipse.core.resources.ResourcesPlugin;
030: import org.eclipse.core.runtime.Path;
031: import org.eclipse.core.runtime.Platform;
032: import org.eclipse.jface.dialogs.IDialogPage;
033: import org.eclipse.jface.viewers.ISelection;
034: import org.eclipse.jface.viewers.IStructuredSelection;
035: import org.eclipse.jface.wizard.WizardPage;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.events.ModifyEvent;
038: import org.eclipse.swt.events.ModifyListener;
039: import org.eclipse.swt.events.SelectionAdapter;
040: import org.eclipse.swt.events.SelectionEvent;
041: import org.eclipse.swt.events.SelectionListener;
042: import org.eclipse.swt.layout.GridData;
043: import org.eclipse.swt.layout.GridLayout;
044: import org.eclipse.swt.widgets.Button;
045: import org.eclipse.swt.widgets.Combo;
046: import org.eclipse.swt.widgets.Composite;
047: import org.eclipse.swt.widgets.Label;
048: import org.eclipse.swt.widgets.Text;
049: import org.eclipse.ui.dialogs.ContainerSelectionDialog;
050: import org.eclipse.ui.forms.HyperlinkSettings;
051: import org.eclipse.ui.forms.widgets.FormText;
052: import org.pentaho.designstudio.editors.actionsequence.ActionSequenceEditorPlugin;
053: import org.pentaho.designstudio.editors.actionsequence.preferences.PreferenceConstants;
054: import org.pentaho.designstudio.messages.Messages;
055: import org.pentaho.designstudio.util.XmlHelper;
056:
057: /**
058: * The "New" wizard page allows setting the container for the new file as well
059: * as the file name. The page will only accept file name without the extension
060: * OR with the extension that matches the expected one (xaction).
061: */
062:
063: public class ActionSequenceNewWizardPage extends WizardPage {
064: public static final String BASE_FILENAME = Messages
065: .getString("ActionSequenceNewWizardPage.UI_UNTITLED_ACTION_NAME"); //$NON-NLS-1$
066: public static final String ACTION_SEQUENCE_FILE_EXTENSION = "xaction"; //$NON-NLS-1$
067:
068: private Text containerText;
069: private Text fileText;
070: private ISelection selection;
071: private Combo templateSelectCB;
072: private FormText templateDescTxt;
073: // private Text templateDescTxt;
074:
075: private List templateNames = new ArrayList();
076: private List templateDesc = new ArrayList();
077: private List templateURIs = new ArrayList();
078: private URI currentURI = null;
079:
080: /**
081: * Constructor for SampleNewWizardPage.
082: *
083: * @param pageName
084: */
085: public ActionSequenceNewWizardPage(ISelection selection) {
086: super ("wizardPage"); //$NON-NLS-1$
087: setTitle(Messages
088: .getString("ActionSequenceNewWizardPage.UI_WIZ_TITLE")); //$NON-NLS-1$
089: setDescription(Messages
090: .getString("ActionSequenceNewWizardPage.UI_WIZ_DESCRIPTION")); //$NON-NLS-1$
091: this .selection = selection;
092: }
093:
094: /**
095: * @see IDialogPage#createControl(Composite)
096: */
097: public void createControl(Composite parent) {
098: Composite container = new Composite(parent, SWT.NULL);
099: GridLayout layout = new GridLayout();
100: container.setLayout(layout);
101: layout.numColumns = 3;
102: layout.verticalSpacing = 9;
103: Label label = new Label(container, SWT.NULL);
104: label
105: .setText(Messages
106: .getString("ActionSequenceNewWizardPage.UI_WIZ_CONTAINER_LABEL")); //$NON-NLS-1$
107:
108: containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
109: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
110: containerText.setLayoutData(gd);
111: containerText.addModifyListener(new ModifyListener() {
112: public void modifyText(ModifyEvent e) {
113: dialogChanged();
114: }
115: });
116:
117: Button button = new Button(container, SWT.PUSH);
118: button
119: .setText(Messages
120: .getString("ActionSequenceNewWizardPage.UI_WIZ_BROWSE_LABEL")); //$NON-NLS-1$
121: button.addSelectionListener(new SelectionAdapter() {
122: public void widgetSelected(SelectionEvent e) {
123: handleBrowse();
124: }
125: });
126: label = new Label(container, SWT.NULL);
127: label
128: .setText(Messages
129: .getString("ActionSequenceNewWizardPage.UI_WIZ_FILE_NAME_LABEL")); //$NON-NLS-1$
130:
131: fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
132: gd = new GridData(GridData.FILL_HORIZONTAL);
133: gd.horizontalSpan = 2;
134: fileText.setLayoutData(gd);
135: fileText.addModifyListener(new ModifyListener() {
136: public void modifyText(ModifyEvent e) {
137: dialogChanged();
138: }
139: });
140:
141: label = new Label(container, SWT.NULL);
142: label
143: .setText(Messages
144: .getString("ActionSequenceNewWizardPage.UI_WIZ_TEMPLATE_LABEL")); //$NON-NLS-1$
145:
146: templateSelectCB = new Combo(container, SWT.READ_ONLY);
147: gd = new GridData(GridData.FILL_HORIZONTAL);
148: gd.horizontalSpan = 2;
149: templateSelectCB.setLayoutData(gd);
150:
151: templateSelectCB.setItems(getTemplateNames());
152: templateSelectCB.select(0);
153:
154: templateDescTxt = new FormText(container, SWT.BORDER
155: | SWT.MULTI);
156: templateDescTxt.setHyperlinkSettings(new HyperlinkSettings(
157: parent.getDisplay()));
158:
159: gd = new GridData(SWT.FILL, SWT.FILL, true, true);
160: gd.horizontalSpan = 3;
161: templateDescTxt.setLayoutData(gd);
162:
163: templateSelectCB.addSelectionListener(new SelectionListener() {
164: public void widgetSelected(SelectionEvent e) {
165: templateSelChanged();
166: }
167:
168: public void widgetDefaultSelected(SelectionEvent e) {
169: templateSelChanged();
170: }
171: });
172:
173: templateSelChanged();
174:
175: initialize();
176: dialogChanged();
177: setControl(container);
178: }
179:
180: void templateSelChanged() {
181: int index = templateSelectCB.getSelectionIndex();
182: // templateDescTxt.setText( (index < 0) ? "" : templateDesc.get( index ).toString(), false, true );
183: if (index >= 0) {
184: templateDescTxt
185: .setText(
186: "<form>\n" + templateDesc.get(index).toString() + "\n</form>", true, true); //$NON-NLS-1$ //$NON-NLS-2$
187: currentURI = (URI) templateURIs.get(index);
188: } else {
189: templateDescTxt.setText("", false, false); //$NON-NLS-1$
190: currentURI = null;
191: }
192: }
193:
194: String[] getTemplateNames() {
195: templateNames.clear();
196: templateDesc.clear();
197: templateURIs.clear();
198:
199: List sortArray = new ArrayList();
200: Enumeration e = ActionSequenceEditorPlugin.getDefault()
201: .getBundle().findEntries(
202: "/templates", "*.xaction", true); //$NON-NLS-1$ //$NON-NLS-2$
203: while (e.hasMoreElements()) {
204: sortArray.add(e.nextElement());
205: }
206:
207: Collections.sort(sortArray, new Comparator() {
208: public int compare(Object o1, Object o2) {
209: return (o2.toString().compareTo(o1.toString()));
210: }
211: });
212:
213: for (int i = 0; i < sortArray.size(); ++i) {
214: URL url = (URL) sortArray.get(i);
215: try {
216: url = Platform.resolve(url);
217: URI uri = new URI(url.toExternalForm().replaceAll(
218: " ", "%20")); //$NON-NLS-1$ //$NON-NLS-2$
219: File f = new File(uri);
220: if (f != null) {
221: Document doc = XmlHelper.getDocFromFile(f);
222: String title = XmlHelper
223: .getNodeText(
224: "/action-sequence/title", doc.getRootElement(), null); //$NON-NLS-1$
225: String descript = XmlHelper
226: .getNodeText(
227: "/action-sequence/documentation/description", doc.getRootElement(), null); //$NON-NLS-1$
228:
229: if (title != null) {
230: if (title.trim().length() > 0) {
231: templateNames.add(title.trim());
232: } else {
233: Path path = new Path(f.getName());
234: templateNames.add(path
235: .removeFileExtension()
236: .lastSegment());
237: }
238: templateDesc
239: .add((descript != null) ? descript
240: : Messages
241: .getString("ActionSequenceNewWizardPage.XML_WIZ_TEMPLATE_NO_DESCRIPTION")); //$NON-NLS-1$
242: templateURIs.add(uri);
243: }
244: }
245: } catch (Throwable t) {
246: System.err
247: .println(Messages
248: .getString("ActionSequenceNewWizardPage.UI_WIZ_TEMPLATE_ERROR_MSG") + url); //$NON-NLS-1$
249: t.printStackTrace();
250: }
251: }
252: return ((String[]) templateNames
253: .toArray(new String[templateNames.size()]));
254: }
255:
256: /**
257: * Tests if the current workbench selection is a suitable container to use.
258: */
259:
260: private void initialize() {
261: if (selection != null && !selection.isEmpty()
262: && selection instanceof IStructuredSelection) {
263: IStructuredSelection ssel = (IStructuredSelection) selection;
264:
265: Object obj = ssel.getFirstElement();
266: if (obj instanceof IResource) {
267: IContainer container;
268: if (obj instanceof IContainer)
269: container = (IContainer) obj;
270: else
271: container = ((IResource) obj).getParent();
272: containerText.setText(container.getFullPath()
273: .toString());
274:
275: String modelFilename = BASE_FILENAME
276: + "." + ACTION_SEQUENCE_FILE_EXTENSION; //$NON-NLS-1$
277: for (int i = 1; container.findMember(modelFilename) != null; ++i) {
278: modelFilename = BASE_FILENAME + i
279: + "." + ACTION_SEQUENCE_FILE_EXTENSION; //$NON-NLS-1$
280: }
281: fileText.setText(modelFilename);
282: }
283: }
284: }
285:
286: /**
287: * Uses the standard container selection dialog to choose the new value for
288: * the container field.
289: */
290:
291: private void handleBrowse() {
292: ContainerSelectionDialog dialog = new ContainerSelectionDialog(
293: getShell(),
294: ResourcesPlugin.getWorkspace().getRoot(),
295: false,
296: Messages
297: .getString("ActionSequenceNewWizardPage.UI_WIZ_NEW_CONTAINER_DLG_MSG")); //$NON-NLS-1$
298: if (dialog.open() == ContainerSelectionDialog.OK) {
299: Object[] result = dialog.getResult();
300: if (result.length == 1) {
301: containerText.setText(((Path) result[0]).toString());
302: }
303: }
304: }
305:
306: /**
307: * Ensures that both text fields are set.
308: */
309:
310: private void dialogChanged() {
311: IResource container = ResourcesPlugin.getWorkspace().getRoot()
312: .findMember(new Path(getContainerName()));
313: String fileName = getFileName();
314:
315: if (getContainerName().length() == 0) {
316: updateStatus(Messages
317: .getString("ActionSequenceNewWizardPage.UI_WIZ_NO_CONTAINER_ERROR_MSG")); //$NON-NLS-1$
318: return;
319: }
320: if (container == null
321: || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) {
322: updateStatus(Messages
323: .getString("ActionSequenceNewWizardPage.UI_WIZ_CONTAINER_NOT_EXIST_MSG")); //$NON-NLS-1$
324: return;
325: }
326: if (!container.isAccessible()) {
327: updateStatus(Messages
328: .getString("ActionSequenceNewWizardPage.UI_WIZ_PROJ_NOT_WRITABLE_MSG")); //$NON-NLS-1$
329: return;
330: }
331: if (fileName.length() == 0) {
332: updateStatus(Messages
333: .getString("ActionSequenceNewWizardPage.UI_WIZ_NO_FILENAME_ERROR_MSG")); //$NON-NLS-1$
334: return;
335: }
336: if (fileName.replace('\\', '/').indexOf('/', 1) > 0) {
337: updateStatus(Messages
338: .getString("ActionSequenceNewWizardPage.UI_WIZ_INVALID_FILENAME_MSG")); //$NON-NLS-1$
339: return;
340: }
341: int dotLoc = fileName.lastIndexOf('.');
342: if (dotLoc != -1) {
343: String ext = fileName.substring(dotLoc + 1);
344: if (ext.equalsIgnoreCase(ACTION_SEQUENCE_FILE_EXTENSION) == false) {
345: updateStatus(Messages
346: .getString("ActionSequenceNewWizardPage.UI_WIZ_INVALID_FILE_EXT_MSG")); //$NON-NLS-1$
347: return;
348: }
349: }
350: updateStatus(null);
351: }
352:
353: public InputStream getInitialContent() {
354: InputStream inputStream = null;
355: String encoding = ActionSequenceEditorPlugin
356: .getDefault()
357: .getPluginPreferences()
358: .getString(
359: PreferenceConstants.ACTION_SEQUENCE_XML_ENCODING);
360: if (currentURI != null) {
361: try {
362: File f = new File(currentURI);
363: if (f != null) {
364: Document document = XmlHelper.getDocFromFile(f);
365: if ((encoding != null)
366: && (encoding.trim().length() > 0)) {
367: document.setXMLEncoding(encoding);
368: }
369: inputStream = new ByteArrayInputStream(document
370: .asXML().getBytes());
371: return inputStream;
372: }
373: } catch (Throwable t) {
374: }
375: }
376: String emptySeq = "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n<action-sequence>\n <inputs/>\n <outputs/>\n <resources/> <actions>\n </actions>\n</action-sequence>"; //$NON-NLS-1$ //$NON-NLS-2$
377: inputStream = new ByteArrayInputStream(emptySeq.getBytes());
378: return inputStream;
379: }
380:
381: private void updateStatus(String message) {
382: setErrorMessage(message);
383: setPageComplete(message == null);
384: }
385:
386: public String getContainerName() {
387: return containerText.getText();
388: }
389:
390: public String getFileName() {
391: return fileText.getText();
392: }
393: }
|