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.controls;
014:
015: import java.lang.reflect.InvocationTargetException;
016: import java.lang.reflect.Method;
017: import java.util.ArrayList;
018: import java.util.HashSet;
019: import java.util.Iterator;
020: import java.util.regex.Matcher;
021: import java.util.regex.Pattern;
022:
023: import org.dom4j.Element;
024: import org.eclipse.swt.SWT;
025: import org.eclipse.swt.dnd.DND;
026: import org.eclipse.swt.dnd.DropTarget;
027: import org.eclipse.swt.dnd.DropTargetEvent;
028: import org.eclipse.swt.dnd.DropTargetListener;
029: import org.eclipse.swt.dnd.Transfer;
030: import org.eclipse.swt.events.ModifyEvent;
031: import org.eclipse.swt.events.ModifyListener;
032: import org.eclipse.swt.widgets.Composite;
033: import org.eclipse.swt.widgets.Control;
034: import org.eclipse.swt.widgets.Text;
035: import org.pentaho.actionsequence.dom.AbstractIOElement;
036: import org.pentaho.actionsequence.dom.ActionInput;
037: import org.pentaho.actionsequence.dom.ActionInputConstant;
038: import org.pentaho.actionsequence.dom.ActionOutput;
039: import org.pentaho.actionsequence.dom.ActionSequenceDocument;
040: import org.pentaho.actionsequence.dom.ActionSequenceInput;
041: import org.pentaho.actionsequence.dom.IActionInputValueProvider;
042: import org.pentaho.actionsequence.dom.IActionInputVariable;
043: import org.pentaho.actionsequence.dom.SimpleActionInputVariable;
044: import org.pentaho.actionsequence.dom.actions.ActionDefinition;
045:
046: public class NewActionInputText implements IActionSequenceControl,
047: ModifyListener {
048: protected Text inputText;
049: protected ActionDefinition actionDefinition;
050: protected String inputName;
051: DropTarget dropTarget;
052: boolean useCData = true;
053: HashSet referencedInputs = new HashSet();
054: HashSet requiredInputs = new HashSet();
055: Method getValueMethod;
056: Method setValueMethod;
057: boolean allowParameterReference = true;
058: boolean allowConstantValue = true;
059:
060: public NewActionInputText(Composite parent, Object layoutData,
061: int style) {
062: inputText = WidgetFactory.createText(parent, "", style); //$NON-NLS-1$
063: if (layoutData != null) {
064: inputText.setLayoutData(layoutData);
065: }
066: initDropTarget();
067: inputText.addModifyListener(this );
068: }
069:
070: public NewActionInputText(Composite parent, Object layoutData) {
071: this (parent, layoutData, SWT.SINGLE | SWT.BORDER);
072: }
073:
074: private void initDropTarget() {
075: dropTarget = new DropTarget(inputText, DND.DROP_MOVE
076: | DND.DROP_COPY | DND.DROP_DEFAULT);
077: dropTarget
078: .setTransfer(new Transfer[] { ActionSequenceParamTransfer
079: .getInstance() });
080:
081: dropTarget.addDropListener(new DropTargetListener() {
082:
083: public void dragEnter(DropTargetEvent event) {
084: if (event.detail == DND.DROP_DEFAULT) {
085: if ((event.operations & DND.DROP_COPY) != 0) {
086: event.detail = DND.DROP_COPY;
087: } else {
088: event.detail = DND.DROP_NONE;
089: }
090: }
091: }
092:
093: public void dragOver(DropTargetEvent event) {
094: }
095:
096: public void dragOperationChanged(DropTargetEvent event) {
097: }
098:
099: public void dragLeave(DropTargetEvent event) {
100: }
101:
102: public void dropAccept(DropTargetEvent event) {
103: }
104:
105: public void drop(DropTargetEvent event) {
106: if (ActionSequenceParamTransfer.getInstance()
107: .isSupportedType(event.currentDataType)) {
108: if ((event.data instanceof ActionSequenceInput)
109: || (event.data instanceof ActionOutput)) {
110: performDrop((AbstractIOElement) event.data);
111: }
112: }
113: }
114: });
115: }
116:
117: public void setTargetInput(ActionDefinition actionDefinition,
118: String inputName) {
119: this .actionDefinition = actionDefinition;
120: if ((inputName != null) && (inputName.trim().length() > 0)) {
121: String propertyName = getPropertyName(inputName);
122: try {
123: getValueMethod = actionDefinition.getClass().getMethod(
124: "get" + propertyName, new Class[0]); //$NON-NLS-1$
125: } catch (Exception ex) {
126: }
127: try {
128: try {
129: setValueMethod = actionDefinition
130: .getClass()
131: .getMethod(
132: "set" + propertyName, new Class[] { IActionInputValueProvider.class }); //$NON-NLS-1$
133: allowConstantValue = true;
134: allowParameterReference = true;
135: } catch (NoSuchMethodException ex) {
136: try {
137: setValueMethod = actionDefinition
138: .getClass()
139: .getMethod(
140: "set" + propertyName, new Class[] { ActionInputConstant.class }); //$NON-NLS-1$
141: allowConstantValue = true;
142: allowParameterReference = false;
143: } catch (NoSuchMethodException ex1) {
144: try {
145: setValueMethod = actionDefinition
146: .getClass()
147: .getMethod(
148: "set" + propertyName, new Class[] { IActionInputVariable.class }); //$NON-NLS-1$
149: allowConstantValue = false;
150: allowParameterReference = true;
151: } catch (NoSuchMethodException ex2) {
152: allowConstantValue = false;
153: allowParameterReference = false;
154: }
155: }
156: }
157: } catch (Exception ex) {
158: allowConstantValue = false;
159: allowParameterReference = false;
160: }
161: } else {
162: getValueMethod = null;
163: setValueMethod = null;
164: }
165: this .inputName = inputName;
166: refresh();
167: }
168:
169: public ActionDefinition getActionDefinition() {
170: return actionDefinition;
171: }
172:
173: public String getInputName() {
174: return inputName;
175: }
176:
177: private void syncInputReferences() {
178: HashSet currentInputReferences = getReferencedInputs();
179: ArrayList addedInputs = new ArrayList();
180: ArrayList removedInputs = new ArrayList();
181: for (Iterator iter = currentInputReferences.iterator(); iter
182: .hasNext();) {
183: String inputName = (String) iter.next();
184: if (!referencedInputs.contains(inputName)) {
185: addedInputs.add(inputName);
186: referencedInputs.add(inputName);
187: actionDefinition.addInputParam(inputName,
188: ActionSequenceDocument.STRING_TYPE);
189: }
190: }
191: for (Iterator iter = referencedInputs.iterator(); iter
192: .hasNext();) {
193: String inputName = (String) iter.next();
194: if (!currentInputReferences.contains(inputName)) {
195: removedInputs.add(inputName);
196: }
197: }
198: for (Iterator iter = removedInputs.iterator(); iter.hasNext();) {
199: String inputName = (String) iter.next();
200: referencedInputs.remove(inputName);
201: Element componentDefElement = (Element) actionDefinition
202: .getElement().selectSingleNode(
203: ActionSequenceDocument.COMPONENT_DEF_NAME);
204: if (componentDefElement.equals(null)
205: || (componentDefElement.asXML().indexOf(
206: "{" + inputName + "}") == -1)) { //$NON-NLS-1$ //$NON-NLS-2$
207: ActionInput actionInput = actionDefinition
208: .getInputParam(inputName);
209: if (actionInput != null) {
210: actionInput.delete();
211: }
212: }
213: }
214: for (Iterator iter = addedInputs.iterator(); iter.hasNext();) {
215: String inputName = (String) iter.next();
216: referencedInputs.add(inputName);
217: actionDefinition.addInputParam(inputName,
218: ActionSequenceDocument.STRING_TYPE);
219: }
220: }
221:
222: public void modifyText(ModifyEvent e) {
223: updateActionSequence();
224: syncInputReferences();
225: }
226:
227: public void refresh() {
228: inputText.removeModifyListener(this );
229: String text = null;
230:
231: if (getValueMethod != null) {
232: try {
233: IActionInputValueProvider actionInput = (IActionInputValueProvider) getValueMethod
234: .invoke(actionDefinition, new Object[0]);
235: if (actionInput instanceof ActionInput) {
236: text = ActionUtil
237: .parameterToDisplayText(((ActionInput) actionInput)
238: .getReferencedVariableName());
239: } else {
240: text = actionInput.getStringValue(false);
241: }
242: } catch (IllegalArgumentException e) {
243: // TODO Auto-generated catch block
244: e.printStackTrace();
245: } catch (IllegalAccessException e) {
246: // TODO Auto-generated catch block
247: e.printStackTrace();
248: } catch (InvocationTargetException e) {
249: // TODO Auto-generated catch block
250: e.printStackTrace();
251: }
252: }
253:
254: inputText.setText(text != null ? text : ""); //$NON-NLS-1$
255: inputText.addModifyListener(this );
256: referencedInputs = getReferencedInputs();
257: }
258:
259: public Control getControl() {
260: return inputText;
261: }
262:
263: public void updateActionSequence() {
264: if (setValueMethod != null) {
265: String txtString = inputText.getText().trim();
266: try {
267: if (allowParameterReference
268: && ActionUtil.isParamDispText(txtString)) {
269: String paramName = ActionUtil
270: .parameterFromDisplayText(txtString);
271: if (paramName.length() == 0) {
272: setValueMethod.invoke(actionDefinition,
273: new Object[] { null });
274: } else {
275: IActionInputVariable[] availInputs = actionDefinition
276: .getAvailInputVariables(ActionSequenceDocument.STRING_TYPE);
277: IActionInputVariable availInput = null;
278: for (int i = 0; i < availInputs.length; i++) {
279: if (availInputs[i].getVariableName()
280: .equals(paramName)) {
281: availInput = availInputs[i];
282: break;
283: }
284: }
285: if (availInput == null) {
286: availInput = new SimpleActionInputVariable(
287: paramName,
288: ActionSequenceDocument.STRING_TYPE);
289: }
290: setValueMethod.invoke(actionDefinition,
291: new Object[] { availInput });
292: }
293: } else if (allowConstantValue) {
294: if (txtString.length() > 0) {
295: setValueMethod.invoke(actionDefinition,
296: new Object[] { new ActionInputConstant(
297: txtString) });
298: } else {
299: setValueMethod.invoke(actionDefinition,
300: new Object[] { null });
301: }
302: }
303: } catch (IllegalArgumentException e) {
304: // TODO Auto-generated catch block
305: e.printStackTrace();
306: } catch (IllegalAccessException e) {
307: // TODO Auto-generated catch block
308: e.printStackTrace();
309: } catch (InvocationTargetException e) {
310: // TODO Auto-generated catch block
311: e.printStackTrace();
312: }
313: }
314: }
315:
316: protected void performDrop(AbstractIOElement io) {
317: String droppedType = io.getType();
318: String droppedName = (io instanceof ActionOutput) ? ((ActionOutput) io)
319: .getPublicName()
320: : io.getName();
321: if ((droppedType != null) && (droppedType.trim().length() > 0)) {
322: if ((io instanceof ActionSequenceInput)
323: && (actionDefinition.getDocument().getInput(
324: io.getName()) != null)) {
325: inputText.setText(ActionUtil
326: .parameterToDisplayText(droppedName));
327: } else if (io instanceof ActionOutput) {
328: ActionOutput droppedOutput = (ActionOutput) io;
329: IActionInputVariable[] availInputs = actionDefinition
330: .getAvailInputVariables(ActionSequenceDocument.STRING_TYPE);
331: for (int i = 0; i < availInputs.length; i++) {
332: if (availInputs[i] instanceof ActionOutput) {
333: ActionOutput availInput = (ActionOutput) availInputs[i];
334: if (availInput.getName().equals(
335: droppedOutput.getName())
336: && availInput.getPublicName().equals(
337: droppedOutput.getPublicName())
338: && availInput.getType().equals(
339: droppedOutput.getType())) {
340: inputText
341: .setText(ActionUtil
342: .parameterToDisplayText(droppedName));
343: break;
344: }
345: }
346: }
347: }
348: }
349: }
350:
351: public void setUseCData(boolean use) {
352: useCData = use;
353: }
354:
355: public boolean getUseCData() {
356: return useCData;
357: }
358:
359: public HashSet getReferencedInputs() {
360: HashSet queryInputs = new HashSet();
361: String queryString = inputText.getText();
362: Pattern pattern = Pattern
363: .compile("\\{[a-zA-Z][a-zA-Z_0-9\\-]+\\}"); //$NON-NLS-1$
364: Matcher matcher = pattern.matcher(queryString);
365: int startIndex = 0;
366: while (matcher.find() && (startIndex < queryString.length())) {
367: String inputName = matcher.group();
368: inputName = inputName.substring(1, inputName.length() - 1);
369: queryInputs.add(inputName);
370: }
371: return queryInputs;
372: }
373:
374: public String getText() {
375: return inputText.getText();
376: }
377:
378: public void setText(String string) {
379: inputText.setText(string);
380: }
381:
382: private String getPropertyName(String inputName) {
383: StringBuffer stringBuffer = new StringBuffer(inputName
384: .toLowerCase());
385: stringBuffer.setCharAt(0, Character.toUpperCase(stringBuffer
386: .charAt(0)));
387: for (int index = stringBuffer.toString().indexOf('-'); index != -1; index = stringBuffer
388: .toString().indexOf('-')) {
389: stringBuffer.deleteCharAt(index);
390: if (index < stringBuffer.length()) {
391: stringBuffer.setCharAt(index, Character
392: .toUpperCase(stringBuffer.charAt(index)));
393: }
394: }
395: for (int index = stringBuffer.toString().indexOf('_'); index != -1; index = stringBuffer
396: .toString().indexOf('_')) {
397: stringBuffer.deleteCharAt(index);
398: if (index < stringBuffer.length()) {
399: stringBuffer.setCharAt(index, Character
400: .toUpperCase(stringBuffer.charAt(index)));
401: }
402: }
403: return stringBuffer.toString();
404: }
405: }
|