
fr.centralesupelec.edf.riseclipse.util.RiseClipseMetamodel Maven / Gradle / Ivy
/*
*************************************************************************
** Copyright (c) 2016-2022 CentraleSupélec & EDF.
** All rights reserved. This program and the accompanying materials
** are made available under the terms of the Eclipse Public License v2.0
** which accompanies this distribution, and is available at
** https://www.eclipse.org/legal/epl-v20.html
**
** This file is part of the RiseClipse tool
**
** Contributors:
** Computer Science Department, CentraleSupélec
** EDF R&D
** Contacts:
** [email protected]
** [email protected]
** Web site:
** https://riseclipse.github.io
*************************************************************************
*/
package fr.centralesupelec.edf.riseclipse.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Optional;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.viewers.ViewerFilter;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class RiseClipseMetamodel {
private static final HashMap< String, RiseClipseMetamodel > knownMetamodels = new HashMap<>();
private static final String XMLNS_ATTRIBUTE_NAME = "xmlns";
private static SAXParser saxParser;
private static final URIConverter uriConverter = new ExtensibleURIConverterImpl();
private static final String METAMODEL_CATEGORY = "RiseClipse/Metamodel";
static {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
try {
saxParser = saxParserFactory.newSAXParser();
}
catch( ParserConfigurationException e ) {
AbstractRiseClipseConsole.getConsole().emergency( METAMODEL_CATEGORY, 0, "RiseClipseMetamodel.static: got ParserConfigurationException ", e );
}
catch( SAXException e ) {
AbstractRiseClipseConsole.getConsole().emergency( METAMODEL_CATEGORY, 0, "RiseClipseMetamodel.static: got SAXException ", e );
}
}
public static void loadKnownMetamodels( @NonNull IRiseClipseConsole console ) {
IConfigurationElement[] contributions = Platform.getExtensionRegistry().getConfigurationElementsFor(
"fr.centralesupelec.edf.riseclipse.main.meta_models" );
for( int i = 0; i < contributions.length; i++ ) {
String uri = contributions[i].getAttribute( "uri" );
if(( uri == null ) || ( uri.isEmpty() )) {
AbstractRiseClipseConsole.getConsole().emergency( METAMODEL_CATEGORY, 0, "RiseClipseMetamodel.loadKnownMetamodels: invalid metamodel URI for RiseClispse" );
return;
}
String name = contributions[i].getAttribute( "name" );
if(( name == null ) || ( name.isEmpty() )) {
AbstractRiseClipseConsole.getConsole().emergency( METAMODEL_CATEGORY, 0, "RiseClipseMetamodel.loadKnownMetamodels: invalid metamodel name for RiseClispse" );
return;
}
String adapterFactoryName = contributions[i].getAttribute( "adapterFactory" );
String resourceFactoryName = contributions[i].getAttribute( "resourceFactory" );
String resourceSetFactoryName = contributions[i].getAttribute( "resourceSetFactory" );
String viewerFilterName = contributions[i].getAttribute( "viewerFilter" );
AdapterFactory newAdapterFactory = null;
IRiseClipseResourceFactory newResourceFactory = null;
IRiseClipseResourceSetFactory newResourceSetFactory = null;
ViewerFilter newViewerFilter = null;
if( knownMetamodels.get( uri ) != null ) {
// We allow for extension point in several plugins (one in the main, another in the edit)
newAdapterFactory = knownMetamodels.get( uri ). getAdapterFactory().orElse( null );
newResourceFactory = knownMetamodels.get( uri ).getResourceFactory().orElse( null );
newResourceSetFactory = knownMetamodels.get( uri ).getResourceSetFactory().orElse( null );
newViewerFilter = knownMetamodels.get( uri ).getViewerFilter().orElse( null );
}
try {
if(( adapterFactoryName != null ) && ! adapterFactoryName.isEmpty() ) {
newAdapterFactory = ( AdapterFactory ) contributions[i].createExecutableExtension( "adapterFactory" );
}
if(( resourceFactoryName != null ) && ! resourceFactoryName.isEmpty() ) {
newResourceFactory = ( IRiseClipseResourceFactory ) contributions[i].createExecutableExtension( "resourceFactory" );
}
if(( resourceSetFactoryName != null ) && ! resourceSetFactoryName.isEmpty() ) {
newResourceSetFactory = ( IRiseClipseResourceSetFactory ) contributions[i].createExecutableExtension( "resourceSetFactory" );
}
if(( viewerFilterName != null ) && ! viewerFilterName.isEmpty() ) {
newViewerFilter = ( ViewerFilter ) contributions[i].createExecutableExtension( "viewerFilter" );
}
}
catch( CoreException e ) {
console.error( METAMODEL_CATEGORY, 0, "Metamodel with uri " + uri + " has invalid factories." );
continue;
}
if( knownMetamodels.get( uri ) == null ) {
console.info( METAMODEL_CATEGORY, 0, "Added metamodel " + name + " for URI " + uri );
}
knownMetamodels.put( uri, new RiseClipseMetamodel( name, newAdapterFactory,
newResourceFactory, newResourceSetFactory, newViewerFilter ));
}
}
@SuppressWarnings( "serial" )
private static class MetamodelFoundException extends SAXException {
private final @NonNull String ns;
public MetamodelFoundException( @NonNull String ns ) {
this.ns = ns;
}
public @NonNull String getMetamodel() {
return ns;
}
}
public static Optional< String > findMetamodelFor( @NonNull URI resourceURI ) {
DefaultHandler defaultHandler = new DefaultHandler() {
@Override
public void startElement( String uri, String localName, String qName, Attributes attributes )
throws SAXException {
for( int i = 0; i < attributes.getLength(); ++i ) {
String furi = attributes.getURI( i );
if( furi.length() == 0 ) {
furi = attributes.getQName( i );
int dc = furi.indexOf( ':' );
if( dc != -1 ) {
furi = furi.substring( 0, dc );
}
}
if( XMLNS_ATTRIBUTE_NAME.equals( furi ) ) {
String ns = attributes.getValue( i );
if( ns.endsWith( "#" )) ns = ns.substring( 0, ns.length() - 1 );
if( knownMetamodels.containsKey( ns )
&& knownMetamodels.get( ns ).getResourceSetFactory().isPresent() ) {
// Stop parsing and give back result
// TODO: can we stop parsing without using an exception ?
throw new MetamodelFoundException( ns );
}
}
}
// no need to look after the root element
throw new MetamodelFoundException( "" );
}
};
String res = null;
try {
InputStream inputStream = uriConverter.createInputStream( resourceURI );
saxParser.parse( inputStream, defaultHandler );
}
catch( MetamodelFoundException e ) {
res = e.getMetamodel();
}
catch( SAXException | IOException e ) {
// Not an xml file or any other error : we will use the standard mechanism
}
finally {
saxParser.reset();
}
return Optional.ofNullable( res );
}
public static boolean isKnown( @NonNull String metamodelURI ) {
// The resourceSetFactory is the criteria for a known metamodel
return knownMetamodels.containsKey( metamodelURI ) && knownMetamodels.get( metamodelURI ).getResourceSetFactory().isPresent();
}
public static Optional< RiseClipseMetamodel > getMetamodel( @NonNull String metamodelURI ) {
if( isKnown( metamodelURI )) {
return Optional.ofNullable( knownMetamodels.get( metamodelURI ));
}
return Optional.empty();
}
public static Collection< RiseClipseMetamodel > getKnownsMetamodels() {
return knownMetamodels.values();
}
private @NonNull String name;
private AdapterFactory adapterFactory;
private IRiseClipseResourceFactory resourceFactory;
private IRiseClipseResourceSetFactory resourceSetFactory;
private ViewerFilter viewerFilter;
public RiseClipseMetamodel( @NonNull String name, AdapterFactory adapterFactory,
IRiseClipseResourceFactory resourceFactory, IRiseClipseResourceSetFactory resourceSetFactory, ViewerFilter filter ) {
super();
this.name = name;
this.adapterFactory = adapterFactory;
this.resourceFactory = resourceFactory;
this.resourceSetFactory = resourceSetFactory;
this.viewerFilter = filter;
}
public @NonNull String getName() {
return name;
}
public Optional< AdapterFactory > getAdapterFactory() {
return Optional.ofNullable( adapterFactory );
}
public Optional< IRiseClipseResourceFactory > getResourceFactory() {
return Optional.ofNullable( resourceFactory );
}
public Optional< IRiseClipseResourceSetFactory > getResourceSetFactory() {
return Optional.ofNullable( resourceSetFactory );
}
public Optional< ViewerFilter > getViewerFilter() {
return Optional.ofNullable( viewerFilter );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy