Programmazione:Java/Eclipse RCP/Visualizzare il contenuto di un XSD in una Tree

Da WikiSitech.
Vai alla navigazioneVai alla ricerca

<< Back to Eclipse RCP

Utilizzo delle classi di eclipse

Eclipse mette a disposizione delle classi che permettono il parsing e la visualizzazione in una Tree di un qualsiasi XSD, andando eventualmente a risolvere le import e le include. Dato che Eclipse utilizza un modello EMF per rappresentare in modo generalizzato l'XSD, per effettuare il parsing bisogna utilizzare le classi Resource di EMF.

import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.provider.XSDItemProviderAdapterFactory;
import org.eclipse.xsd.util.XSDResourceFactoryImpl;
import org.eclipse.xsd.util.XSDResourceImpl;

XSDSchema loadXSD(String URL) {
   Map option = new HashMap();
   option.put("XSD_TRACK_LOCATION", Boolean.TRUE);
	
   XSDItemProviderAdapterFactory syntacticAdapterFactory = new XSDItemProviderAdapterFactory();
   BasicCommandStack commandStack = new BasicCommandStack();
		
    try {
      xsdResource.load(editingDomain.getResourceSet().getLoadOptions());
   } catch (IOException e) {
      e.printStackTrace();
   }
   return xsdResource.getSchema();
}

Per visualizzare lo schema XSDSchema in una tree bisogna utilizzare il TreeViewer di jface e impostargli come provider le classi di Eclispe

import java.util.Collections;
import org.eclipse.emf.edit.provider.ItemProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.provider.XSDItemProviderAdapterFactory;
import org.eclipse.xsd.provider.XSDSemanticItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;

Tree getViewXSDTree(Composite parent, XSDSchema schema) {
   Tree tree = new Tree(parent, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);

   TreeViewer viewer = new TreeViewer(tree);
   viewer.setAutoExpandLevel(3);
		
   XSDItemProviderAdapterFactory semanticAdapterFactory = new XSDSemanticItemProviderAdapterFactory();
   viewer.setContentProvider(new AdapterFactoryContentProvider(semanticAdapterFactory));
   viewer.setLabelProvider(new AdapterFactoryLabelProvider(semanticAdapterFactory));
   viewer.setInput(new ItemProvider(Collections.singleton(schema)));
   return tree;
}

Naturalmente sia il ContentProvider che il LabelProvider sono definiti per visualizzare l'XSD nel modo standard di eclipse, per personalizzare questa visualizzazione bisogna estendere queste classi.

Esempio di personalizzazione della visualizzazione

In questo esempio sono stati estesi sia il Content che il Label provider, in modo da visualizzare solo elementi ed attributi, cambiando inoltre l'icona associata al tipo di elemento.

Estensione del ContentProvider

public class XsdAdapterFactoryContentProvider extends AdapterFactoryContentProvider {
	public XsdAdapterFactoryContentProvider(AdapterFactory adapterFactory) {
		super(adapterFactory);
	}

	@Override
	public Object[] getElements(Object object) {
		Object[] elements = super.getElements(object);
		if(elements.length == 1 && elements[0] instanceof XSDSchema) {
			elements = super.getElements(elements[0]);
			for(int i = 0; i < elements.length; i++) {
				ItemProvider item = (ItemProvider)elements[i];
				if("Elements".equals(item.getText())) {
					elements = super.getElements(item);
				}
			}
		}
		return elements;
	}
	
	@Override
	public Object[] getChildren(Object object) {
		return parseElement(object, 0).toArray();
	}
	
	private List<Object> parseElement(Object object, int level) {
		Object[] elements = super.getChildren(object);
		List<Object> ret = new ArrayList<Object>();  
		for(int i = 0; i < elements.length; ) {
			if(elements[i] instanceof XSDComplexTypeDefinition && !"anyType".equals(((XSDComplexTypeDefinition)elements[i]).getName())) {
				ret.addAll(parseElement(elements[i], level+1));
			}
			else if(elements[i] instanceof XSDParticle) {
				XSDParticle par = (XSDParticle)elements[i];
				if(par.getContent() instanceof XSDModelGroup) {
					ret.addAll(parseElement(elements[i], level));
				}
				else {
					ret.add(elements[i]);
				}
			}
			else if(elements[i] instanceof XSDAttributeUse && level <= 1) {
				XSDAttributeUse use = (XSDAttributeUse)elements[i];
				ret.add(use.getContent());
			}
			++i;
		}
		return ret;		
	}
	
	@Override
	public boolean hasChildren(Object object) {
		if(getChildren(object).length > 0) {
			return true;
		}
		return false;
	}
}

Estensione del LabelProvider

public class XsdAdapterFactoryLabelProvider extends AdapterFactoryLabelProvider {

	public XsdAdapterFactoryLabelProvider(AdapterFactory adapterFactory) {
		super(adapterFactory);
	}


	@Override
	public Image getColumnImage(Object object, int columnIndex) {
		if(columnIndex == 0) { 
			if(object instanceof XSDAttributeDeclaration) {
				return Activator.getImageDescriptor("/images/attribute.gif").createImage();
			}
			return Activator.getImageDescriptor("/images/element.gif").createImage();
		}
		return null;
	}

	@Override
	public String getColumnText(Object object, int columnIndex) {
		if(columnIndex == 0) { 
			return super.getColumnText(object, columnIndex);
		}
		else {
			Object obj = object;
			if(object instanceof XSDParticle) {
				obj = ((XSDParticle)object).getContent();
			}
			if(obj instanceof XSDElementDeclaration) {
				XSDElementDeclaration element = (XSDElementDeclaration)obj;
				if(element.getAnnotation() != null) {
					return getAnnotation(element.getAnnotation().getElement());
				}
			}
			else if(obj instanceof XSDAttributeDeclaration) {
				XSDAttributeDeclaration attr = (XSDAttributeDeclaration)obj;
				if(attr.getAnnotation() != null) {
					return getAnnotation(attr.getAnnotation().getElement());
				}
			}
		}
		return "";
	}
	
	private String getAnnotation(Element e) {
		String ret = null;
		NodeList childs = e.getChildNodes();
		for(int i = 0; i < childs.getLength(); i++) {
			Node child = childs.item(i);
			if("xs:documentation".equals(child.getNodeName())) {
				return child.getTextContent();
			}
		}
		return ret;
	}
}

Utilizzo nella tree

Tree getViewXSDTree(Composite parent, XSDSchema schema) {
   Tree tree = new Tree(composite, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
   
   tree.setHeaderVisible(true);
   tree.setLinesVisible(true);

   TreeColumn nodeColumn = new TreeColumn(tree, SWT.LEFT);
   nodeColumn.setText("Nodo");
   nodeColumn.setWidth(150);

   TreeColumn desColumn = new TreeColumn(tree, SWT.LEFT);
   desColumn.setText("Descrizione");
   desColumn.setWidth(220);

   TreeViewer viewer = new TreeViewer(tree);
   viewer.setAutoExpandLevel(3);
		
   XSDItemProviderAdapterFactory semanticAdapterFactory = new XSDSemanticItemProviderAdapterFactory();
   viewer.setContentProvider(new XsdAdapterFactoryContentProvider(semanticAdapterFactory));
   viewer.setLabelProvider(new XsdAdapterFactoryLabelProvider(semanticAdapterFactory));
   viewer.setInput(new ItemProvider(Collections.singleton(schema)));
   return tree;
}