User-defined editor code example for handling change notifications

Use the example Java™ code to create a user-defined editor that updates the value of the parameter when there are changes to other pattern parameters.

About this task

The following example code shows you how to write user-defined editor code to handle change notifications from other pattern parameters. The user-defined editor, assigned to pattern parameter months, displays a list of the months of the year, one or more of which the pattern user can select by using check boxes. A second pattern parameter, uncheck month, displays a list of the months of the year in a drop-down list. When the pattern user selects a month in the uncheck month parameter, the user-defined editor code receives a change notification from uncheck month and that month is cleared in the list of months in the user-defined editor.

The MyEditor class controls the function of the editor. The MyComposite class controls the appearance of the editor by using methods and objects from the SWT toolkit.

The example assumes that the following steps are completed:
  1. The pattern parameters, months and uncheck month are added to the user-defined pattern. To add pattern parameters, see Defining the user interface.
  2. An enumerated type is created that contains the months of the year. The enumerated type is assigned to pattern parameter, uncheck month. To use enumerated types, see Using enumerated values for pattern parameters.
  3. The pattern parameter, months, is configured to use a user-defined editor; see Defining the user interface.
  4. The user-defined editor for pattern parameter, months, is configured by completing the following steps. For more information about configuring a user-defined editor, see Configuring a user-defined editor.
    1. The MyEditor class is entered in the Configure User-Defined Editor window, in the Class name field.
    2. The pattern parameter, uncheck month, is selected in the Configure User-Defined Editor window, in the Select the visible parameters which will send change notifications to this user defined editor field.
MyEditor class
The MyEditor class extends the BasePatternPropertyEditor class. An instance of the MyEditor class is created automatically when the pattern user opens the pattern instance editor.
  1. The configureEditor() method is called automatically after the MyEditor class is created.
  2. The createControls() method is called to create the user interface for the editor. The controls are defined in the MyComposite class.
  3. The isValid() method is called automatically after the valueChanged() method is called. In this example, isValid() checks the current value of the pattern parameter and returns an error message if no value is selected. The error message is displayed to the pattern user in the pattern instance editor. If the parameter value is valid, the method returns null.
  4. The setValue(), getValue(), and setEnabled() methods are defined in the MyComposite class:
    1. The setValue() method sets the initial value in the user-defined editor.
    2. The getValue() method returns the current value of the pattern parameter to the pattern instance editor.
    3. The setEnabled() method is called when the pattern parameter is enabled or disabled by an XPath expression.
  5. The notifyChanged() method calls the uncheckMonth() method in the MyComposite class, passing the value of the parameter, uncheck month. The notifyChanged() method also takes the ID of the updated pattern parameter, but this is not used in this example.
package com.your.company.domain.MyPattern.code;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;

import com.ibm.broker.config.appdev.patterns.ui.BasePatternPropertyEditor;
import com.ibm.broker.config.appdev.patterns.ui.PatternPropertyEditorSite;

public class MyEditor extends BasePatternPropertyEditor {
   private MyComposite composite;
	
   @Override
   public void configureEditor(PatternPropertyEditorSite site, boolean required, String configurationValues) {
      super.configureEditor(site, required, configurationValues);
   }

   @Override
   public void createControls(Object parent) {
      Composite parentComposite = (Composite) parent;
      PatternPropertyEditorSite site = getSite();
      composite = new MyComposite(parentComposite, SWT.NONE, site);
   }

   @Override
   public String isValid() {
      String selection = getValue();
      if (selection != null) {
         return null;
      }
      return "Nothing currently selected..!";
   }
	
   @Override
   public void setValue(String value) {
      if (value != null) {
         composite.setValue(value);
      }
   }
	
   @Override
   public String getValue() {
      return composite.getValue();
   }
	
   @Override
   public void setEnabled(boolean enabled) {
      composite.setEnabled(enabled);
   }
	
   @Override
   public void notifyChanged(String parameterId, String value) {
      composite.uncheckMonth(value);
   }
}
MyComposite class
The MyComposite class creates the user interface controls for the user-defined editor. The MyComposite class extends the SWT toolkit Composite class.
  1. The layout of the controls is set and a new table control is created.
  2. The valueChanged() method is used in a listener on the table control. This ensures that when the selected values in the table are changed, change notifications are sent to any XPath expressions or editors that use the value of this parameter.
  3. A table item is created for each month of the year.
  4. The setValue(), getValue(), and setEnabled() methods are defined in the MyComposite class, but are called from the MyEditor class:
    1. The setValue() method takes the value of the pattern parameter and updates the table control to show the selected values. The value of the parameter is stored as an XML document in string format that contains the list of months and information about whether each month is selected. The setValue() method reads each month, whether it is selected, and updates the check boxes in the table.
    2. The getValue() method retrieves the currently selected values from the table in the user-defined editor. The list of months and the check box status of each month is stored in an XML document, which is saved as a string value. This string is returned to the MyEditor class and then to the pattern instance editor. The string is stored as the current value of the parameter.
    3. The uncheckMonth() method takes the value of the parameter, uncheck month, passed from the MyEditor class. The month is checked against the list of months in the table and when a match is found, the check box for that month is cleared in the user-defined editor.
    4. The setEnabled() method uses the boolean value passed to it to enable or disable the table control.
package com.your.company.domain.MyPattern.code;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.ibm.broker.config.appdev.patterns.ui.PatternPropertyEditorSite;

public class MyComposite extends Composite {
   private PatternPropertyEditorSite site;
   private Table table;
	
   public static String[] MONTHS = { 
      "January", "February", "March", "April", "May", "June", "July", 
         "August", "September", "October", "November", "December" };
	
   public MyComposite(Composite parent, int style, final PatternPropertyEditorSite site) {
      super(parent, SWT.NONE);
      this.site = site;
		 		
      GridLayout gridLayout = new GridLayout(1, false);
      setLayout(gridLayout); 		
 		
      setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
 		
      table = new Table(this, SWT.BORDER | SWT.CHECK);
      table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
      table.setLinesVisible(true);

      table.addSelectionListener(new SelectionAdapter() {
         @Override
         public void widgetSelected(SelectionEvent event) {
            site.valueChanged();
         }
      });

      for (String currentMonth : MONTHS) {
         TableItem currentItem = new TableItem(table, SWT.NONE);
         currentItem.setText(currentMonth);
      }
   }
	
   public void setValue(String value) {
		
      try {

         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         DocumentBuilder builder = factory.newDocumentBuilder();
         InputSource inputSource = new InputSource(new StringReader(value));
         Document document = builder.parse(inputSource);
         NodeList listOfMonths = document.getDocumentElement().getChildNodes();
			
         for (int index = 0; index < listOfMonths.getLength(); index++) {
            Node monthNode = listOfMonths.item(index);			
            String monthName = monthNode.getNodeName();
            boolean checked = Boolean.parseBoolean(monthNode.getTextContent());
                
            for (TableItem tableItem : table.getItems()) {
               String itemName = tableItem.getText();
               if (itemName.equals(monthName) == true) {
                  tableItem.setChecked(checked); break;
               }
            }
         }
      } catch (Exception exception) { }
   }

   public String getValue() {
		
      try {
			
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         DocumentBuilder builder = factory.newDocumentBuilder();
         Document document = builder.newDocument();
         Element rootElement = document.createElement("months");
	        
         document.appendChild(rootElement);
            
         for (TableItem currentItem : table.getItems()) {
            String monthName = currentItem.getText();
            boolean isChecked = currentItem.getChecked();
            Element monthElement = document.createElement(monthName);
            monthElement.setTextContent(Boolean.toString(isChecked));
            rootElement.appendChild(monthElement);
         }
            
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
         transformer.setOutputProperty(OutputKeys.INDENT, "yes");

         StringWriter stringWriter = new StringWriter();
         StreamResult result = new StreamResult(stringWriter);
         DOMSource source = new DOMSource(document);
         transformer.transform(source, result);
         return stringWriter.toString();
            
      } catch (Exception exception) { }

      return null;
   }
	
   public void uncheckMonth(String monthName) {
      for (TableItem tableItem : table.getItems()) {
         String itemName = tableItem.getText();
         if (itemName.equals(monthName) == true) {
            tableItem.setChecked(false); break;
         }
      }
   }
	
   public void setEnabled(boolean enabled) {
      table.setEnabled(enabled);
   }
}