Programmazione:Java/Eclipse RCP/Visualizzare il contenuto di un XSD in una Tree
Indice
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;
}