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