Friday, May 7, 2010

How to convert DB Schema into UML Class using Eclipse API ?

Converting DB Schema into UML Classes

We provide a sample case-study about how to leverage the powerful modeling frameworks of eclipse (Semantic Notation management using EMF , Diagram Graphics management using MF and Draw2d, Standard Visual Representation using UML)
Users can drag the Database schema/table/tablespce and drop onto a custom UML editor.
After tables are are converted into uml classes, we apply stereotype and profile to retain the original DB info.
Step 1 :  Contributing custom edit policy provider to GMF editor
 In our DnD handler plugin, we contribute com.pramati.tools.dnd.policies.CustomEditPolicyProvider to the org.eclipse.gmf.runtime.diagram.ui.editpolicyProviders.
 The Object class should specify the object that has to be examined by this provider. Considering a UML class Diagram Editor the object class would be “org.eclipse.uml2.diagram.clazz.edit.parts.PackageEditPart” as it is the root edit part onto which objects should be dropped.
  

     
        
        

        
        

        
  



This Presentation Edit Policy Provider extension point is used to define editpolicy providers for the editpolicy service. The editpolicy service allows plug-ins to modify or enhance the behavior of an editpart via an editpolicy without modifying the editpart code.     Step 2 :  Install Edit Policy for CANONICAL_ROLE  and DRAG_DROP_ROLE on EditPart of the Diagram Editor that extends DiagramEditPart. The Canonical edit policy will ensure that the host's model children are in sync with a specific set of semantic children. It will register itself with the model server to receive semantic events fired to its host editpart. It will create, if necessary, notation elements for all semantic elements inserted into the host element or delete the notation element for the semantic element removed from the host element. CanonicalConnectionEditPolicy is a specialized implementation of CanonicalEditPolicy. It will manage connections owned by the semantic host. public class CustomDragDropEditPolicy extends DragDropEditPolicy { public void createEditPolicies(EditPart editPart) {                           if (editPart instanceof PackageEditPart)  {                         editPart.installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new  CustomCanonicalConnectionEditPolicy());               editPart.installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE,                                                  new CustomDnDEditPolicy();                         editPart.getViewer().addDropTargetListener(                                                                                   new CustomDragDropTargetListner(editPart().getViewer()));                                          }             }   Note : Very important point to note while installing Canonical Edit policy is that the target editPart on which we install the edit policy should be specific to the Diagram Editor and should not be GraphicalEditPart as it would effect the creation of notation elements for all other GMF Editors.   public boolean provides(IOperation operation) {             if(operation instanceof CreateEditPoliciesOperation){                   EditPart editPart = ((CreateEditPoliciesOperation) operation).getEditPart();                return isEditPartValid(editPart);             }             return false; Step 3  : Prepare the list of objects to be dropped and set it on the Drop Request @Override       protected List<> getObjectsBeingDropped() {           
            ISelection selection =
                  LocalSelectionTransfer.getInstance().getSelection();       
            if (selection instanceof IStructuredSelection) {
                  sourceObjectList = ((IStructuredSelection) selection).toList();
            }           
            return sourceObjectList;
      }
 
@Override
protected Request createTargetRequest() {      
DropObjectsRequest req = new DropObjectsRequest();
req.setObjects(getObjectsBeingDropped());
            return req;
      }
 
Step-4 :  Provide implementation for CustomCanonicalConnectionEditPolicy class           
Every Diagram Editor provides its custom implementation of CanonicalConnectionEditPolicy, say in the Mindmap example it is provided by MapCanonicalEditPolicy  class and in Taipan example it is provided by the PortCanonicalEditPolicy class. Use this custom implementation and override allowDropElement(Object dropElement) method to allow custom objects to be dropped . This method by default only allows dropping of objects which are an instance of org.eclipse.gmf.runtime.notation.Diagram.  Now, for example if we want to drop a table or scheme from DataSourceExplorer the implementation would be as follows:
            @Override
            protected boolean allowDropElement(Object dropElement)
            {
                        if(dropElement instanceof Diagram || dropElement instanceof BaseTable ||                                                dropElement instanceof Schema)
                                    return true;
                        else return false;
            }


Step 5: Return an edit part that can produce an executable command for the target              request
 
      private EditPart calculateTargetEditPart() {
            updateTargetRequest();
            EditPart ep = getViewer()
                  .findObjectAtExcluding(
                        getDropLocation(),
                        getExclusionSet(),
                        new EditPartViewer.Conditional() {
                              public boolean evaluate(EditPart editpart) {
                                    Command command =
editpart.getCommand(getTargetRequest());                               
                                    return command != null;
                              }
                        });
           if (ep != null) {
                  Command command = ep.getCommand(getTargetRequest());
                  return (command != null && command.canExecute())? ep : null;                 
            }
            return ep;
      }
 
Step 6: Return the required DnD command from the corresponding Edit Part
      @Override
      public Command getCommand(Request _request) {
            if(_request instanceof DropObjectsRequest) {   
                  return getDnDEditPolicy().getCommand(_request);
            }else {    
                  return super.getCommand(_request); 
            }
      }
 
      /**
      * @generated NOT
      * @return
      */
      private EditPolicy getDnDEditPolicy() {
            EditPolicy dndPolicy = null;
            EditPolicyIterator i = getEditPolicyIterator();      
            while (i.hasNext()) {        
                  EditPolicy tempPolicy = i.next();        
                  if (tempPolicy instanceof DragDropEditPolicy) {      
                        dndPolicy = tempPolicy;      
                        break;           
                  }
            }          
            return dndPolicy;
      }
// Custom Edit Policy
public class CustomDragDropEditPolicy extends DragDropEditPolicy {
@Override
      protected Command getDropElementCommand(EObject element, DropObjectsRequest
request) {
            EObject modelObj = getHostObject();      
            TransactionalEditingDomain editDomain = (TransactionalEdit
ingDomain)WorkingCopyUtil.getWorkingCopyFor(modelObj).getEditingDomain();
            return getGMFWrapper(new
CustomDragDropCommand(editDomain,request,modelObj,element));
            }
     
      private Command getGMFWrapper(ICommand gmfCommand){
            return new ICommandProxy(gmfCommand);
      }
//------
}
 
Step 7 : Execute the DnD Command to create the Concepts through corresponding    Generator class
 
public class BOMADragDropCommand extends AbstractTransactionalCommand{
     
      private EObject modelObj;
      private EObject element;     
      private IDataModelGenerator modelGen;    
 
      /**
       *
       * @param editDomain
       * @param request
       * @param modelObj
       * @param element
       */
      public CustomDragDropCommand (TransactionalEditingDomain
editDomain,DropObjectsRequest request,EObject modelObj,EObject element){
            super(editDomain,"DND",getAffectedFiles(request));
            this.modelObj = modelObj;
            this.element = element;            
      }    
     
      @Override
      protected CommandResult doExecuteWithResult(IProgressMonitor monitor,
IAdaptable info) throws ExecutionException {
            Model model = null;          
            //
            if(modelObj != null){
                  if(modelObj instanceof Model){
                        model = (Model)modelObj;
                  int elementType =
DropElementTypeResolver.getElementType(element);
                        switch(elementType){
                             case DropElementTypeResolver.DB_TYPE:
modelGen = new
DB2UMLModelGenerator((Model)modelObj);
                                    modelGen.generateUMLModel(element);
                                    modelGen.setRelationships();
                                    break;
                              case DropElementTypeResolver.JAVA_TYPE:
                                    break;
                              case DropElementTypeResolver.XSD_TYPE:
                                    break;
                        }                                        
                  }
            }    
            return CommandResult.newOKCommandResult();
      }    
     
      private static List getAffectedFiles(Request request){           
            return null;
      }    
}

No comments: