Categorías
Architecture & Design

Mecanismo de complemento de Eclipse

La plataforma Eclipse se basa en el marco OSGi.

El marco del complemento Eclipse es bastante complejo. Sin embargo, las ideas generales detrás son muy simples. En esta publicación, la idea simple de cómo funciona un complemento se explica mediante el uso de un diagrama. Luego, se crea un complemento de Eclipse simple para explicar cómo agregar un elemento de menú a la barra de menú.

En el modelo Eclipse, cada complemento funciona por encima de la plataforma Eclipse. Cada complemento puede estar relacionado con otro complemento mediante una de estas dos relaciones:

1. Dependencia. En el diagrama anterior, el complemento A depende del complemento B.
2. Ampliación. En el diagrama anterior, el complemento A amplía el complemento C.

Categorías
Architecture & Design

Arquitectura del marco OSGi: tres capas conceptuales

El marco OSGi (iniciativa Open Services Gateway) proporciona una arquitectura modular dinámica que se ha utilizado en muchas aplicaciones como Eclipse Equinox, Apache Felix, etc. Comprender cómo funciona el marco OSGi es útil para desarrollar complementos de Eclipse y muchas otras aplicaciones de molecularidad. En este artículo, se explica la descripción general de alto nivel de la arquitectura.

La arquitectura del marco OSGi consta de tres capas conceptuales. Cada capa depende de la (s) capa (s) debajo de ella. El siguiente diagrama describe la descripción general de cada capa.

Capa de módulo

La capa de módulo define el concepto de módulo OSGi: paquete, que es un archivo JAR con metadatos adicionales. Un paquete contiene archivos de clase y recursos relacionados, como imágenes, archivos xml.

A través del archivo de metadatos manifest.mf, la capa de módulo declara qué paquetes contenidos en el archivo JAR son visibles desde el exterior y declara de qué paquetes externos depende el paquete.

Algunos ejemplos de metadatos:
Paquete de exportación: com.programcreek.helloexport
Declara qué paquetes son visibles para los usuarios.
Paquete de importación: com.programcreek.helloimport
Declara cuándo se requieren paquetes externos.

Capa de ciclo de vida

Esta capa define cómo se instalan y administran dinámicamente los paquetes en el marco OSGi. Proporciona una forma para que un paquete obtenga acceso al marco OSGi subyacente.

Si OSGi fuera un automóvil, la capa de módulos proporcionaría módulos como llantas, asientos, etc., y la capa de ciclo de vida proporcionaría el cableado eléctrico que hace que el automóvil funcione.

Capa de servicio

En esta capa, los proveedores de servicios publican servicios en el registro de servicios, mientras que los clientes de servicios buscan en el registro los servicios disponibles para usar.

Esto es como una arquitectura orientada a servicios (SOA) que se ha utilizado ampliamente en servicios web. Aquí los servicios OSGi son locales para una sola máquina virtual, por lo que a veces se llama SOA en una máquina virtual.
* Parte del contenido es del libro «OSGi en acción».

Categorías
Architecture & Design Design Patterns Stories

Patrones de diseño utilizados en la plataforma Eclipse

Aquí resumo los patrones de diseño utilizados en la plataforma Eclipse. Comprender los patrones de diseño utilizados en Eclipse es la clave para comprender la plataforma Eclipse.

La arquitectura Eclipse tiene una estructura de capas claras. Cada capa es independiente entre sí pero interactiva entre sí. Para comprender mejor un marco, es una buena idea comenzar desde una vista general de la idea de patrones de diseño subyacente.

Esto es solo un resumen, se ilustran los patrones de diseño utilizados en cada capa.

  • Tiempo de ejecución de la plataforma: Adaptador (Parte 1, Parte 2, Parte 3), Singleton
  • Espacio de trabajo: proxy y puente, compuesto, observador, visitante
  • SWT: Compuesto, Estrategia, Observador
  • JFace: estrategia, comando
  • Mesa de trabajo: Memento, Visual Proxy

Categorías
Architecture & Design

Cómo funciona el complemento Eclipse: análisis de un menú simple

Al utilizar el asistente de complementos de Eclipse, no se necesita tiempo para obtener un complemento de muestra que funcione. Aquí hay uno que hice para conseguir un menú.

En este sencillo ejemplo se puede ilustrar cómo funciona un complemento de eclipse.

Activador clase es el punto de inicio del complemento. La clase Activator se carga inicialmente y si observa la jerarquía de la clase Activator, amplía el AbstractUIPlugin, que le dice al tiempo de ejecución de Eclipse que este complemento está relacionado de alguna manera con la interfaz de usuario de la plataforma Eclipse.

El método getDefault () será llamado por el tiempo de ejecución de Eclipse para devolver la instancia del complemento. Dado que solo hay una instancia de la clase Plugin, la clase Activator se mantiene como una Clase Singleton al tener una variable estática compartida de tipo Activator.

package simplemenu;
 
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
 
/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends AbstractUIPlugin {
 
	// The plug-in ID
	public static final String PLUGIN_ID = "SimpleMenu";
 
	// The shared instance
	private static Activator plugin;
 
	/**
	 * The constructor
	 */
	public Activator() {
	}
 
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
	}
 
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		plugin = null;
		super.stop(context);
	}
 
	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static Activator getDefault() {
		return plugin;
	}
 
	/**
	 * Returns an image descriptor for the image file at the given
	 * plug-in relative path
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}
}

El archivo Plugin.xml se utiliza para inicializar el complemento para el proceso anterior.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
 
   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            label="Sample Action Set"
            visible="true"
            id="SimpleMenu.actionSet">
         <menu
               label="Sample &amp;Menu"
               id="sampleMenu">
            <separator
                  name="sampleGroup">
            </separator>
         </menu>
         <action
               label="&amp;Sample Action"
               icon="icons/sample.gif"
               class="simplemenu.actions.SampleAction"
               tooltip="Hello, Eclipse world"
               menubarPath="sampleMenu/sampleGroup"
               toolbarPath="sampleGroup"
               id="simplemenu.actions.SampleAction">
         </action>
      </actionSet>
   </extension>
 
</plugin>

Aquí está el código que implementa una acción. Su jerarquía es la siguiente:

IWorkbenchWindowActionDelegate es el que se implementa aquí, pero otro tipo de acción puede implementar otra interfaz, por ejemplo, IObjectActionDelegate.

Tenga en cuenta que run () es el método de devolución de llamada al que llamará su proxy. La devolución de llamada es un concepto en patrón de diseño del observador.

package simplemenu.actions;
 
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;
 
/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class SampleAction implements IWorkbenchWindowActionDelegate {
	private IWorkbenchWindow window;
	/**
	 * The constructor.
	 */
	public SampleAction() {
	}
 
	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		MessageDialog.openInformation(
			window.getShell(),
			"SimpleMenu",
			"Hello, Eclipse world"+ action.toString());
	}
 
	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}
 
	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}
 
	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
}

Categorías
Architecture & Design

Decipher Eclipse Architecture: IAdaptable – Parte 2 – Ejemplo simple

Patrón de diseño de adaptador

¿Cómo se utiliza el patrón de diseño del adaptador en la plataforma Eclipse? Eclipse Platform Runtime tiene un buen ejemplo de este patrón.

En primer lugar, el patrón de diseño del adaptador tiene una idea simple detrás: envolver el objeto y hacerlo compatible con otra interfaz que esperan los clientes. Puedes echar un vistazo a la idea de adaptador más simple en mi publicación anterior.

La forma en que se utilizan los adaptadores en eclipse es ligeramente diferente y más compleja. En el siguiente ejemplo, las clases y las interfaces se colocan en un archivo por motivos de simplicidad.

La jerarquía de clases se muestra en el diagrama siguiente.

Cuando queremos pasar de naranjas a manzanas, el adaptador entra en su lugar. El siguiente código muestra lo que hace, ningún flujo de trabajo complejo de Eclipse.

interface IAdaptable{
	public Object getAdapter(Class adapter);
}
 
interface IApple extends IAdaptable{ }
 
interface IOrange{ }
 
class Orange implements IOrange{ }
 
interface IPear{ }
 
class Pear implements IPear{ }
 
public class Apple implements IApple{	
	@Override
	public Object getAdapter(Class adapter) {
		//the real story should be forwarding the request to the platform to get adapter
		return PlatformAdapterManager.getAdapter(this, adapter);
	}	
}
 
class PlatformAdapterManager{
	public static Object getAdapter(Object o, Class adapter){
		if(adapter == IOrange.class){
			if(o instanceof Apple){
				return new Orange(); //Read code use an adapter to wrap the apple object and return an adapter object which implements IApple interface
			}
		}else if(adapter == IPear.class){
			if(o instanceof Apple){
				return new Pear();
			}
		}
		return null; //return null when the class does not implement the interface.
	}
}

La clase PlatformAdapterManager está totalmente inventada, la historia real en eclipse es que la plataforma obtiene el administrador del adaptador para devolver un adaptador adecuado.

public class Main {	
	public static void main(String args[]){
		IApple apple = new Apple();
		IOrange orange = (IOrange)apple.getAdapter(IOrange.class);
 
		if(orange == null){
			System.out.println("null");
		}else{
			System.out.println(orange);
		}
 
		IPear pear = (IPear)apple.getAdapter(IPear.class);	
		if(pear == null){
			System.out.println("null");
		}else{
			System.out.println(pear);
		}
	}
}

Producción:
[email protected]
[email protected]

Este es el enfoque de implementar el método getAdapter () en la propia clase. Este enfoque no requiere registro con la clase, ya que la implementación está en el método getAdapter ().

De otra manera que se usa en Eclipse, no se requieren cambios de código en la clase, el método getAdapter es aportado por una fábrica. Echa un vistazo a esta publicación para ver la historia real.

Referencias:

artículo de esquina.

Categorías
Architecture & Design

Decipher Eclipse Architecture: IAdaptable – Parte 3 – Mostrar propiedades de elementos en una vista

Este ejemplo muestra cómo se usa IAdaptable en Eclipse en un ejemplo real. Para tener una idea de cómo funciona el patrón de diseño del adaptador en Eclipse, vaya a esas publicaciones: post1 post2.

Suponga que ha creado una vista utilizando el «Asistente de extensión» de eclipse. (Si no sabe esto, intente jugar y hacer esto).

Y ahora cambie el código en SampleView.java para que sea el siguiente:

package adapterview.views;
 
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.*;
import org.eclipse.swt.SWT;
 
public class SampleView extends ViewPart {
 
	private TableViewer viewer;
 
	class ViewLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		public String getColumnText(Object obj, int index) {
			TestItem testItem = (TestItem) obj;
			return testItem.getSummary();
		}
 
		public Image getColumnImage(Object obj, int index) {
			return getImage(obj);
		}
 
		public Image getImage(Object obj) {
			return PlatformUI.getWorkbench().getSharedImages()
					.getImage(ISharedImages.IMG_OBJ_ELEMENT);
		}
	}
 
	/**
	 * This is a callback that will allow us to create the viewer and initialize it.
	 */
 
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		viewer.setContentProvider(new ArrayContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		getSite().setSelectionProvider(viewer);
		viewer.setInput(getElements());
 
	}
 
/**
	 * Passing the focus request to the viewer's control.
	 */
 
	public void setFocus() {
		viewer.getControl().setFocus();
	}
 
	// Build up a simple data model
	private TestItem[] getElements() {
		TestItem[] testItems = new TestItem[2];
		TestItem testItem = new TestItem();
		testItem.setSummary("First Item");
		testItem.setDescription("A very good description");
		testItems[0] = testItem;
		testItem = new TestItem();
		testItem.setSummary("Second Item");
		testItem.setDescription("Another very good description");
		testItems[1] = testItem;
		return testItems;
	}
}

TestItem.java

package adapterview.views;
public class TestItem {
	private String summary;
	private String description;
	public String getSummary() {
		return summary;
	}
	public void setSummary(String summary) {
		this.summary = summary;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
}

Básicamente, esto creará una vista y se mostrará como esta figura.

¿Qué sucede si quiero mostrar el resumen y la descripción en una vista de propiedad cuando se hace clic en cada elemento? Puede pensar en cambiar alguna parte del código en SampleView, pero la plataforma Eclipse es increíble y no hay necesidad de cambiar en esta clase.

Lo que necesitamos es agregar un adaptador para TestItem Class.

Ahora agregue el siguiente fragmento al archivo plugin.xml.

<extension
         point="org.eclipse.core.runtime.adapters">
      <factory
            adaptableType="adapterview.views.TestItem"
            class="adapterplace.TestItemAdapterFactory">
         <adapter
               type="org.eclipse.ui.views.properties.IPropertySource">
         </adapter>
      </factory>
</extension>

Esto declara las siguientes tres clases:

1. adaptableType es TestItem
2. la fábrica para crear el adaptador para adaptableType (TestItem) es TestItemAdapterFactory
3. El adaptador es IPropertySource, que es necesario para que la vista de propiedades muestre propiedades.

Recuerde el ejemplo de manzana y naranja en mi publicación anterior, ahora aquí queremos ir de TestItem a IPropertySource.

La jerarquía de archivos de archivos es así:

TestItemAdapterFactory.java

package adapterplace;
 
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.ui.views.properties.IPropertySource;
import adapterview.views.*;
 
public class TestItemAdapterFactory implements IAdapterFactory {
 
	@Override
	public Object getAdapter(Object adaptableObject, Class adapterType) {
		if (adapterType== IPropertySource.class && adaptableObject instanceof TestItem){
			return new TestItemAdapter((TestItem) adaptableObject);
		}
		return null;
	}
 
	@Override
	public Class[] getAdapterList() {
		// TODO Auto-generated method stub
		return null;
	}
}

TestItemAdapter.java: esta clase envuelve un objeto TestItem con los métodos de IPropertySource, que a su vez son requeridos por la vista de propiedades.

package adapterplace;
 
import adapterview.views.TestItem;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
 
 
public class TestItemAdapter implements IPropertySource {
	private final TestItem testItem;
 
	public TestItemAdapter(TestItem testItem) {
		this.testItem = testItem;
	}
 
 
	@Override
	public boolean isPropertySet(Object id) {
		return false;
	}
 
	@Override
	public Object getEditableValue() {
		return this;
	}
 
	@Override
	public IPropertyDescriptor[] getPropertyDescriptors() {
 
		return new IPropertyDescriptor[] {
				new TextPropertyDescriptor("summary", "Summary"),
				new TextPropertyDescriptor("description", "Description") };
	}
 
	@Override
	public Object getPropertyValue(Object id) {
		if (id.equals("summary")) {
			return testItem.getSummary();
		}
		if (id.equals("description")) {
			return testItem.getDescription();
		}
		return null;
	}
 
	@Override
	public void resetPropertyValue(Object id) {
 
	}
 
	@Override
	public void setPropertyValue(Object id, Object value) {
		String s = (String) value;
		if (id.equals("summary")) {
			testItem.setSummary(s);
		}
		if (id.equals("description")) {
			testItem.setDescription(s);
		}
	}
}

Resultado: cuando se selecciona un elemento en la vista de muestra, la vista de propiedades muestra su propiedad.

Referencia:

IPropertySource

Categorías
Architecture & Design

Arquitectura de complementos de Eclipse: procesamiento de extensiones

Esta publicación comienza con la pregunta: cómo se llama al método de devolución de llamada en la plataforma Eclipse.

La respuesta corta es: el complemento de host llama al método de devolución de llamada.

El ejemplo utilizado es de una publicación anterior que trata sobre la creación de un complemento de muestra con un menú a través del asistente de complementos. Creo que cualquiera que haya jugado un poco con el plug-in lo ha usado antes.

El primer diagrama ilustra la relación entre un complemento de host y un complemento de extensión.
Como todo en Eclipse es un complemento, la interfaz de usuario no es una excepción. Nuestra acción de muestra amplía su punto de extensión ActionSet. También hay muchos otros puntos de extensión que compartirían el mismo principio de devolución de llamada.

El segundo diagrama se usa para mostrar cómo el complemento del host llama al método run (). (En otros casos, en lugar de Action, podría ser createPartControl (padre compuesto) u otros).

PluginAction desempeña el papel de proxy y hace que el objeto de devolución de llamada real se cree una instancia solo cuando se requiere alguna acción.

A continuación, se muestran algunos datos del diagrama a continuación:
PluginAction implementa el método run () de IAction.
PluginAction tiene una instancia IActionDelegate.
El método run () de PluginAction envuelve el método run () de IActionDelegate.

Este patrón se llama: Proxy virtual.

Para obtener el código completo de PluginAction.java, consulte 2 puntos del código de Google.

Este es uno de los conceptos más importantes de Eclipse, pronto habrá más detalles …

Referencias:

1. Arquitectura del complemento Eclipse

Categorías
Architecture & Design

Decipher Eclipse Architecture: IAdaptable – Parte 1 – Breve introducción

Si lee el código fuente de Eclipse, encontrará que IAdaptable es una interfaz muy popular que es implementada por muchos otros. ¿Por qué tantas clases / interfaces implementan IAdaptable? La respuesta es que Adapter es el patrón de diseño principal para eclipse Core Runtime.

¿Qué es IAdaptable?

public interface IAdaptable {
	/**
	 * Returns an object which is an instance of the given class
	 * associated with this object. Returns <code>null</code> if
	 * no such object can be found.
	 *
	 * @param adapter the adapter class to look up
	 * @return a object castable to the given class, 
	 *    or <code>null</code> if this object does not
	 *    have an adapter for the given class
	 */
	public Object getAdapter(Class adapter);
}

IAdaptable se utiliza para el soporte de la extensión Eclipse. Adapta una clase existente a otra interfaz. El método getAdapter devuelve un objeto convertible a la interfaz dada.

Vale la pena mencionar que adaptar una clase significa obtener una clase contenedora que es un subtipo del objetivo. La clase contenedora envuelve al adaptado.

¿Por qué necesitamos IAdaptable?

A medida que se agregan nuevas características al sistema, y ​​esas nuevas características requieren servicios proporcionados por la clase existente, necesitamos hacer que los servicios existentes sean aplicables a las nuevas características (es decir, la clase).

Un ejemplo típico es la vista Propiedades de Eclipse. Presenta un conjunto de propiedades del objeto seleccionado. Cuando selecciona cualquier elemento en la vista Pacakge o en la vista Jerarquía, la vista de propiedades mostrará las propiedades del elemento seleccionado.

La vista de propiedades necesita una interfaz para obtener las propiedades y luego mostrarlas. La interfaz es IPropertySource.

El complemento org.eclipse.resources proporciona interfaces como IResource, IFile, IFolder, etc. Si queremos que la vista de propiedades muestre las propiedades de IFile, una forma es permitir que IFile extienda IPropertySource. Esto funcionará, pero hay varios problemas de esta solución.

public interface IFile extends IPropertySource

En primer lugar, se debe cambiar un objeto IFile para implementar métodos de IPropertySource. En segundo lugar, es posible que necesitemos IFile para implementar muchas otras interfaces, entonces el resultado sería inflado.

Si un objeto IFile implementa la interfaz IAdapter, entonces

	public Object getAdapter(Class adapter){
		if(adapter.equals(IPropertySource.class)){
			return new PropertySourceAdapter(this);
		}
		return null;
	}
	class PropertySourceAdapter implements IPropertySource{	
		private final Object item;
 
		public PropertySourceAdapter(Object item){
			this.item = item;
		}
		//required methods of IPropertySource ...
	}

De esta manera, los objetos que implementan la interfaz IAdaptable se pueden adaptar fácilmente a cualquier interfaz dada.

En realidad, esta no es la solución utilizada en eclipse, porque esto requiere cambios de clase IFile. Cuando lea la parte 3 de IAdaptable, encontrará que IFile no debe cambiarse. El adaptador está configurado en el archivo plugin.xml.

Categorías
Architecture & Design Design Patterns Stories

Patrones de diseño de Eclipse: proxy y puente en el espacio de trabajo

1. Patrón de proxy y puente en Core Workspace

Los patrones de diseño más importantes utilizados en Core Workspace se denominan «Proxy y Bridge». La pregunta más confusa es sobre qué parte es proxy o qué parte es puente.

El siguiente diagrama utiliza IResource para la demostración, otros son similares como IFile, IFolder, IProject, IWorkspaceRoot, etc.

IResource - Proxy y Bridge

En un espacio de trabajo, cada recurso está representado por un identificador. El identificador actúa como una llave para un recurso. Los mangos son objetos pequeños y siempre cambiarán una vez creados.

Resource es el proxy de ResourceInfo. Todo lo solicitado a ResourceInfo se maneja a través de su proxy Resource.
Resource es el implementador de IResource. Dado que solo hay un implementador para un identificador, esto se denomina Puente simplificado.

Proxy: si todo lo que hace A siempre se hace a través de B, entonces B es el proxy de A. Esto puede no ser preciso, pero explica cómo debemos entender el diagrama de clases.
El puente es un patrón similar al adaptador. En el patrón Bridge, definimos tanto la interfaz abstracta como la implementación subyacente. No queremos que se adapte a ninguna interfaz. Normalmente, hay varias implementaciones en lugar de una en este ejemplo.

No es importante mapear los patrones de diseño que conoce con el patrón utilizado aquí, porque no son obvios. Comprender cómo funciona es más útil.

2. Ejemplo de código

Aquí hay un ejemplo de código que puede ilustrar cómo funciona este patrón.

IResource resource=ResourcesPlugin.getWorkspace().getRoot().findMember(path);
  if (resource == null) {
    return null;
  }
IJavaElement javaElement=JavaCore.create(resource);
  if (javaElement == null) {
    return null;
  }
  return javaElement;

Vale la pena mencionar que el modelo Java en JDT usa el mismo diseño.

Categorías
Architecture & Design Design Patterns Stories

Patrones de diseño de Eclipse: compuesto en el espacio de trabajo

Compuesto en el espacio de trabajo

El patrón compuesto define una jerarquía de árbol que permite a los clientes tratar los objetos en la jerarquía de manera uniforme.

En Eclipse Workspace, IWorkspace es la interfaz raíz y es un compuesto de IContainers e IFiles. Aquí está el diagrama de jerarquía de la interfaz.

IResourceHierarchy

Ejemplo de código

A continuación, se muestra un ejemplo para mostrar cómo obtener proyectos en Workspace.

IWorkspace workspace=ResourcesPlugin.getWorkspace();
  IProject[] projects=workspace.getRoot().getProjects();
  for (int i=0; i < projects.length; i++) {
    IProject project=projects[i];
    System.err.println(projectSelectionTable.getData(project.getName()));
    if ((project.isOpen()) && (projectSelectionTable.getData(project.getName()) == null)) {
      projectSelectionTable.add(project);
    }
  }