3d com

 

Adding a New List Dialog

How to add a new dialog and execute multiple server commands from it
Use Case

Abstract

This article shows how to add a new panel in the Portal transient area and execute multiple Update Object commands from it.


What You Will Learn With This Use Case

This use case is intended to help you add a new dialog in the Portal transient area. This dialog is created with the CATJDialog APIs. It is displayed by selecting one or more rows in a list and clicking a new icon added to the Toolbar and the Contextual Menu.

[Top]

The CAALCANavCustoList Use Case

CAALCANavCustoList is a use case of the CAALCANavigator.edu framework that illustrates the LCANavigator customization capabilities.

[Top]

What Does CAALCANavCustoList Do

For CAALCANavCustoList create a new command named custolist and associate a new icon with it. For the command to be executed, implement the execute function in a class extending LCANavCommand. Finally create a new CATJDialog panel named CustoList which controller is CAALcnCustoListController.java

[Top]

How to Launch CAALCANavCustoList

To launch CAALCANavCustoList, you will need to set up the build time environment, customize the runtime view, then compile CAALCANavCustoList along with its prerequisites, set up the run time environment, and then execute the use case [1].

Customize the untime view: Replace in the runtime view CustoTestGeneric.xml and rename it to Generic.xml

[Top]

Where to Find the CAALCANavCustoList Code

The CAALCANavCustoList use case is made of a single module CAALcnCustoList.mj module of the CAALCANavigator.edu framework:

Windows InstallRootDirectory\CAALCANavigator.edu\CAALcnCustoList.mj\
Unix InstallRootDirectory/CAALCANavigator.edu/CAALcnCustoList.mj/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed.

[Top]

Step-by-Step

To create the custolist command and its panel, there are four steps:

  1. Creating a the New Command
  2. Creating a New Icon for the Command
  3. Implementing the execute Function
  4. Creating the New CATJDialog Panel

[Top]

Creating a the New Command

Name the new command: custolist.

To map the new command to the desired action defined in the new command class :

Create/Update manually the properties files to be deployed in the runtime view.

Create:/resources/pprregistry/command/definition/custolist.xml with the following content:

<Command name="custolist" readonly="true" icon="$/I_CMD_custolist.gif" msgcatalog="CustoList"/>

Update (for this new command to apply to all LCA types): /resources/pprregistry/command/ENOVIA/assignment/Generic.xml

Add the following line:

<Command  name="custolist"    multiRowEnabled="false" enablement="true"  visibility="true"/>

[Top]

Creating a New Icon for the Command

Create a new icon of 16x16 pixels identifying the new command on the Toolbar/Contextual menu:

[Top]

Implementing the execute Function

In the new class CAALcnCustobase.CAALcnCustocmds.command.custolist.Generic.java extending LCANavCommand implements the execute function:

This new class implement the "custolist" command for the object type "Generic" (the parent of all types.)
  • Retrieve the UUIDs of the selected objects and make sure that at least one is retrieved
  • For each UUID find the highest WebType parent and make sure it is the same for all.
  • Stack the CustoproList panel with the UUIDs for which the new list will be displayed
...
public void execute( CATSession iSession ){
  //Get the list of input objects
  String[] uuids = getUUIDs( iSession );
  if( uuids == null || uuids.length == 0 ) {
    return;
  }
  String webType = null;
  String prevWebType = null;
  ENOVIDataObject[] queryResults = new ENOVIDataObject[uuids.length];
  for( int i=0; i<uuids.length; i++){
    queryResults[i] =  LCANavUtils.getDataObject( iSession, uuids[i], ENOVTypeMask.EDIT_MASK );
    ENOVWebType type = queryResults[i].getWebType();
    //Check that all selected objects derive from the same parent and pass
    //parent name to the CulstoList dialog
    //This is done prior calling ErrorOncheckAttributes(), because two objects deriving
    //from two different parents may have identical attribute names.

    //For that find the highest WebType parent except GENERIC, DOCCOMMON, ACTCOMMON, RSCBASE
    String parentName = null;
    webType = type.getNoun();
    while (true) {
      parentName = type.getParent();
      if (parentName == null
        || parentName.equalsIgnoreCase("GENERIC")
        || parentName.equalsIgnoreCase("DOCCOMMON")
        || parentName.equalsIgnoreCase("ACTCOMMON")
        || parentName.equalsIgnoreCase("RSCBASE"))
      {
        break;
      }else{
        webType = parentName;
        type = ENOVWebType.getWebType(parentName);
      }
    }
    if (prevWebType == null)
	  prevWebType = webType;
	else {
	  if (! prevWebType.equals(webType) ) {
	    MessageStack.pushInfoMessage( "custolist", "ObjectsOfDifferentTypes", null, iSession );
		showStatusMessage( iSession, false );
		return;
	  }
	}
  }
  if ( ! ErrorOncheckAttributes(queryResults))  {
    MessageStack.pushInfoMessage( "custolist", "ObjectsOfDifferentTypes", null, iSession );
	showStatusMessage( iSession, false );
	return;
  }
  iSession.setVolatileProperty("ENOVIDataObjects", queryResults);
  String parms = "DATAOBECTS=ENOVIDataObjects"+";"+"WEBTYPE="+webType;
  this.stackSingleObjectDialog( iSession, "CustoList", parms );
}
...

Because of type the customization which allows for additonal attributes on derived types, check for same attribute names for all selected objects and same editable attribute names for all selected objects. There is still a risk that two new attributes on two derived types of the same parent have the same name but are of different types. This risk is minimal and checking type equality is not necessary.

...
private boolean ErrorOncheckAttributes(ENOVIDataObject[] iQueryResults) {
  Vector vAttr = null;
  Vector vEditableAttr = null;
  int iNrAtt = 0;
  int iNrEditAtt=0;
  boolean bFirst = true;
  for (int i=0; i<iQueryResults.length; i++ ) {
    if (vEditableAttr == null) {
      vEditableAttr = new Vector();
      vAttr = new Vector();
    }else{
      bFirst = false;
    }
    Enumeration e = iQueryResults[i].getAttributes();
    int iTotalAtt=0;
    int iEditAtt=0;
    while(e.hasMoreElements()){
      ENOVIAttribute att = (ENOVIAttribute)e.nextElement();
      iTotalAtt++;
      if (bFirst) {
        vAttr.addElement(att.getName());
      }else
        if ( ! vAttr.contains(att.getName()))
          return false;

      if (att.isEditable()){
        iEditAtt++;
        if (bFirst){
          vEditableAttr.addElement(att.getName());
        }else
          if ( ! vEditableAttr.contains(att.getName()))
            return false;
      }
    }
    if (iNrAtt  == 0){
      iNrAtt  = iTotalAtt;
      iNrEditAtt = iEditAtt;
    }else{
      if (iTotalAtt != iNrAtt || iEditAtt != iNrEditAtt)
        return false;
    }
  }
  return true;
}
...

[Top]

Creating the New CATJDialog Panel

Create the new CATJDialog panel CustoList to be displayed in the transient area. The new controller extends LCANavDialogController

Call super in Create for the controller to automatically retrieve the document:

...
  public void onCreate(CATDialog iDialog, CATNotification iNotification, Object iData){
    super.onCreate( iDialog, iNotification, iData );
    _btnSelectAll.setTitle("Select All");
    _date = new CATDateEditor( _frameActions, "date" );
    _frameActions.setConstraints( _date, new GC(3, 0, 1, 1, GC.LEFT|GC.TOP, GC.NOFILL) );
    _date.setVisibility(false);
    _select = new CATComboBox( _frameActions, "select" );
    _frameActions.setConstraints( _select, new GC(3, 0, 1, 1, GC.LEFT|GC.TOP, GC.NOFILL) );
    _select.setVisibility(false);
    _text = new CATTextField( _frameActions, "text" );
    _frameActions.setConstraints( _text, new GC(3, 0, 1, 1, GC.LEFT|GC.TOP, GC.NOFILL) );
    _text.setVisibility(false);
 }
...

Implement the onDocumentChanged method:

  • Retrieve the selected UUIDs
  • Retrieve the corresponding objects
  • Fill the table with the retrieved objects
  • Fill combo box with editable column names
  • Select all rows
...
public void onDocumentChanged(CATDialog iDialog, CATNotification iNotification, Object iData) {
  String dataObjects = (String)getParameter("DATAOBECTS");
  _queryResults = (ENOVIDataObject[])iDialog.getSession().getVolatileProperty(dataObjects);
  _webType = (String)getParameter("WEBTYPE");
  if (fillTable())
    fillColumnComboBox();
  onSelectAll( iDialog, iNotification, iData);
}
  ...

Fill the list table with objects

  • Retrieve logon token
  • Create a ENOVDataPPRTablemodel
  • Add the model to the table to display the list
...
  private boolean fillTable(){
	if( _queryResults == null || _queryResults.length == 0 )
	  return false;
	_model = new ENOVDataPPRTableModel( _tableResults, _webType, _queryResults, getLogonToken(), true);
	_model.setPreferencePrefix("custolist");//List Specific Preferences
	_tableResults.setKeyModel( _model );
	_tableResults.setMultipleSelection( true );
	return true;
  }
  ...

Upon column selection fill combo box:

...
  private void fillColumnComboBox(){
    ENOVIDataObject dob = _queryResults[0];
    Enumeration e = dob.getAttributes();
    while(e.hasMoreElements()) {
  	  ENOVIAttribute attr = (ENOVIAttribute)e.nextElement();
  	  if (attr.isEditable()  && ! (attr.getName().indexOf("ID")>-1))
  		_cbColumns.addItem(attr.getAlias());
  	}
  	if (_cbColumns.getItemCount()>0){
  	  _cbColumns.setSelection(0);
  	  onColumnSelected(_cbColumns,null, null );
  	}
  }
  ...

onColunnSelected callback:

  • Loop in the rows
  • Depending on the object type displays the right widget
  • Fill the widget with authorized or help values
...
  public void onColumnSelected(CATDialog iDialog, CATNotification iNotification, Object iData){
	String textDefaultValue = null;
	Vector vAllAuthorizedValues = new Vector();
	_vCommonIntValue = new Vector();
	_vCommonExtValue = new Vector();
	int index = ((CATComboBox)iDialog).getSelectionIndex();
	for (int i=0; i<_queryResults.length; i++){
	  ENOVIDataObject dataObj =  _queryResults[i];
	  Enumeration enum = dataObj.getAttributes();
	  while (enum.hasMoreElements()){
	    ENOVIAttribute attr = (ENOVIAttribute)enum.nextElement();
	    String sal = attr.getAlias();
	    if (attr.getAlias().equals(((CATComboBox)iDialog).getSelection())) {
	      _changedAttrName = attr.getName();
	      ENOVAttributeType attType = attr.getType();
	      if( attType == ENOVAttributeType.DATE_TYPE ) {
	      if (i==0) {
	        _date.setVisibility(true);
	        _select.setVisibility(false);
	        _text.setVisibility(false);
	        Object attrVal = attr.getDefaultInternalValue();
            if( attrVal instanceof Date ){
	          CATDate cDate = new CATDate( (Date)attrVal );
	          _date.setDate( cDate );
	        }
	      }
	    } else if (attr.valueTranslatable()) {
	      if ( i==0 ){
	        _date.setVisibility(false);
	        _select.setVisibility(true);
	        _text.setVisibility(false);
	        getComboValues(attr);
	      }
	    }else{
	      if ( i==0 ){
	        _date.setVisibility(false);
	        _select.setVisibility(false);
	        _text.setVisibility(true);
	        _text.setText("");
	        _text.setExpectedFormat( "" );
	        if (attr.isRequired())
	          _text.setExpectedFormat( "." );
	        if (attType.equals(ENOVAttributeType.INTEGER_TYPE)){
	          if (attr.isRequired())
	            _text.setExpectedFormat("^[0-9]+$");
	          else
	            _text.setExpectedFormat("^[0-9]*$");
	        }
	        Object attrVal = attr.getDefaultExternalValue();
	        if( attrVal != null ){
	          if( attrVal instanceof String[] )
	            _text.setText( arrayToString((String[])attrVal) );
	        }
	      }
	    }
	  }
    }
    if (_select.isDisplayed()){
      try{
	    if (_vCommonIntValue != null){
	      _select.setItems(_vCommonIntValue.elements());
	      String[] extValues = new String[_vCommonExtValue.size()];
	      _vCommonIntValue.copyInto(extValues);
	      _select.setItemTranslator( new LCACATTranslator(_select.getItemList(), extValues, false ) );
	    }
	  }catch (Exception e) {;}
	}
  }
    ...

Retrieve authorized and help values for combo box

...
  private void getComboValues(ENOVIAttribute attr){
	String[] extValue = null;
	String[] intValue = attr.getInternalAuthorizedValues();
	if( intValue != null && intValue.length > 0 ) {
	   extValue = attr.getAuthorizedValues();
	}else{
	   intValue = attr.getInternalHelpValues();
	   extValue = attr.getHelpValues();
	}
  }
        ...

Unstack the panel on onCancel calback

...
  public void onCancel(CATDialog iDialog, CATNotification iNotification, Object iData){
	CATDocumentManager docManager = CATDocumentManager.getDocumentManager(_dialogBox);
	if (docManager != null)
	  docManager.unstack();
  }
        ...

onApply callback. Update objects

...
  public void onApply(CATDialog iDialog, CATNotification iNotification, Object iData){
	String[] keys = _tableResults.getSelectedKeys();
	if (keys == null){
	  MessageStack.pushInfoMessage( "custolist", "NoRowSelected", null, iDialog.getSession());
	  showStatusMessage( false );
	  return;
	}else{
	  _bSave = save(keys, iDialog, iNotification, iData);
	}
  }
          ...

onOK callback: Execute onApply + onCancel

...
  public void onOK(CATDialog iDialog, CATNotification iNotification, Object iData){
	_bSave = false;
	onApply(iDialog, iNotification, iData);
	if (_bSave)
	  onCancel(iDialog, iNotification, iData);
  }
            ...

onSelectall callback

...
  public void onSelectAll(CATDialog iDialog, CATNotification iNotification, Object iData){
	PortalUID[] puid = LCAJPortalUtils.getPortalUIDs(iDialog.getSession(),_queryResults );
	String[] keys = new String[puid.length];
	for (int i=0; i<puid.length; i++)
	  keys[i] = puid[i].toString();
	_tableResults.setSelectedKeys(keys);
  }
              ...

Retrieve the selected objects on which to apply the update

...
   private ENOVIDataObject getDataObjectFromKey(String key, CATSession iSession){
	 PortalUID[] puid = LCAJPortalUtils.getPortalUIDs(iSession,_queryResults );
	 for (int i=0; i< puid.length; i++){
	   if (puid[i].toString().equals(key))
	     return _queryResults[i];
	 }
	 return null;
   }
                ...

Save method. Update all selected objects

...
  private boolean save(String[] keys, CATDialog iDialog, CATNotification iNotification, Object iData) {
	boolean bSaveOk = true;
	for (int i=0; i<keys.length; i++){
	  EVIDataObject dobj = getDataObjectFromKey( keys[i], iDialog.getSession());
	  if (updateDataObject( dobj)){
	    boolean ok = validateDataObject(dobj);
	    if (ok){
		  ENOVIClientCommand cmd = ENOVCommandFactory.createClientCommand( getCommandName(dobj), getLogonToken() );
		  cmd.setParameter( "object", dobj, false );
		  ok = cmd.execute();
		  MessageStack.pushMessages( cmd, _session, i==0? true : false );
		  showStatusMessage( ok );
		  if (!ok) {
		    restoreObject(dobj);
			bSaveOk = false;
		  }
		}else{
		  restoreObject(dobj);
		  bSaveOk = false;
		}
	  }else{
	    MessageStack.pushInfoMessage( "custolist", "RequiredField", null, iDialog.getSession());
	    bSaveOk = false;
	  }
	}
	showStatusMessage( bSaveOk );
	return bSaveOk;
  }
                  ...

Return server command name

...
   private String getCommandName(ENOVIDataObject dataObj){
	 String noun = dataObj.getObjectType();
	 String cmd = ENOVWebType.getWebType( noun ).getCommandName( "lcaedit" );
	 if( cmd == null ) cmd = "UpdateObjectCommand";
	   return cmd;
   }
                  ...

Update object to be saved

...
   private boolean updateDataObject( ENOVIDataObject iDataObj){
	 boolean ok = false;
	 ENOVIType type = iDataObj.getType();
	 Enumeration enum = type.getAttributes();
	 while( enum.hasMoreElements() ){
	   ENOVIAttribute attr = (ENOVIAttribute)enum.nextElement();
	   if (attr.getName().equals(_changedAttrName)){
	     ENOVAttributeType attrType = attr.getType();
	     Object val = null;
	     if( attrType == ENOVAttributeType.DATE_TYPE ){
		   CATDate cDate = _date.getDate();
		   if( cDate != null )
		     val = new Date( cDate.getTime() );
		 }
		 else if( attr.valueTranslatable() ){//Combo box and Check box
		   val = _select.getSelection();
		 }else{
		   val = _text.getText();
		 }
		 if( val != null ){
		   if ( ! (attr.isRequired() &&  ((String)val).length() == 0)){
		     iDataObj.setAttrValue( attr.getID(), val );
		     ok = true;
           }
		 }
	   }
	 }
	 return ok;
   }
                    ...

Restore object if save failed

...
   private void restoreObject( ENOVIDataObject dobj){
	 String uuid = dobj.getObjectUUID();
	 ENOVIDataObject oldObj = LCANavUtils.getDataObject( _dialogBox.getSession(), uuid, ENOVTypeMask.EDIT_MASK );
	 for (int i=0; i<_queryResults.length; i++){
	   if (_queryResults[i].equals(dobj)){
	     _queryResults[i] = oldObj;
	     break;
	   }
	 }
   }
                  ...

Validate object before saving

...
   private boolean validateDataObject( ENOVIDataObject iObject ){
	 boolean ok = true;
	 Enumeration attrEnum = iObject.getType().getAttributes();
	 while( attrEnum.hasMoreElements() ){
	   ENOVIAttribute attr = (ENOVIAttribute)attrEnum.nextElement();
	   if( attr.isRequired() ){
		 Object val = iObject.getAttrValue( attr );
		 boolean thisOneOk = true;
		 if( val == null ){
		   thisOneOk = false;
		 }
	     else if( String.valueOf(val).trim().length() == 0 ){
		   thisOneOk = false;
		 }
         if( !thisOneOk ){
		   ok = false;
		   String[] parms = new String[] { attr.getAlias() };
		   MessageStack.pushErrorMessage( "custolist", "Message.MissingRequired", parms, _session );
		 }
	   }
	 }
	 return ok;
   }
                    ...

Create the CustoList.CATNls file with the following content for all new NLS values

Title="My Customized List";

NoRowSelected = "No row has been selected";

RequiredField = "Field is required";

NotUpdatableObject = "This type of object cannot be updated in LCANav";

ObjectsOfDifferentTypes = "Selection must comprise objects of the same type";

OnlyOneObjectSelected = "More then one row must be selected";

SelectAll.Title = "Select All";

Frame1.FrameToolbar.SelectAll.Title = "Select All";

Command.custolist.title = "Customized List";

[Top]


In Short

This use case shows hwo to create a command that can be executed from a new CATJDialog panel in the Portal transient area. First a new comand is created thanks to RADE, and a new icon is associated with it. Then the command code is created by extending LCANavCommand to implement the execute function. The CATJDialog panel is finally created along with its different callbacks to allow for triggering the server command. 

[Top]


References

[1] Building and Launching a CAA V5 Use Case
[Top]

History

Version: 1 [Jun 2005] Document created
[Top]

Copyright © 1994-2005, Dassault Systèmes. All rights reserved.