Coder Social home page Coder Social logo

devboost / jamopp Goto Github PK

View Code? Open in Web Editor NEW
17.0 17.0 18.0 12.12 MB

JaMoPP can parse Java source and byte code into EMF-based models and vice versa. It preserves source formatting and can be used for code analysis and refactoring.

Java 98.61% HTML 0.29% C# 1.01% CSS 0.08%

jamopp's People

Contributors

cwende avatar jjohannes avatar jreimone avatar mirkoseifert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jamopp's Issues

Java Library class access Improvements

Obeserved High Amount of Method Calls

Within java model classes, standard library classes such as java.lang.Object are accessed through CommentableImpl.getLibClass(String)
getlibclass_search

There are already some convienience methods provided by CommentableImpl such as getObjectClass()
However, even those methods call the getLibClass(String) methods for every call by themselves.

Profiling a parse process for a short time already shows a lot of requests send to getLibClass even through getObjectClass().
getstdclasses

Extensive Processing

There are two important issues for that:

1) Repetitive Calls

Methods such as getObjectClass() call getLibClass(String) with the same string parameter every time. So the result is always the same

    public org.emftext.language.java.classifiers.Class getObjectClass() {
        return getLibClass("Object");
    }

2) Complex Processing in getLibClass(String)

getLibClass(String) internally uses a complex processing for every request including String concatenation, EcoreUtil resolving, instanceof checks, etc.

Improvements

There are two major and one minor recommendations to improve this:

1. Use Caching

Change convenience methods such as getObjectClass() to cache the result and do not forward each request to getLibClass().
Example:

    public org.emftext.language.java.classifiers.Class getObjectClass() {
        if(objectClass == null) {
            objectClass = getLibClass("Object"); 
        }
        return objectClass;
    }
    private org.emftext.language.java.classifiers.Class objectClass = null;

Note:
Important things to consider for this caching

  • A static cache won't work for two or more parsings running in the same JVM.
  • Preloading the cache during class initialization might fail du to missing runtime library availability at class initialization.

2. Additional Convenience Methods with Caching

Introduce additional convenience methods for other standard library classes accessed statically within the meta model implementation.
In addition to java.lang.Object or java.lang.String, other java.lang classes such as java.lang.Integer are accessed in a repetitive manner. For those accesses, similar cache enabled convinience methods can be introduced and the pimitive getLibClass() calls can be replaced.

Improvement Evaluation

To check the number of getLibClass() invocations, parallel parsings of the two variants of the Calculator Example available at http://sdqweb.ipd.kit.edu/wiki/Calculator_Example was performed. Even with this small example, the number of getLibClass() invocation could be significantly reduced using the recommendations described above:

Code Version #invocations of getLibClass()
original implementation 2483
caches for getObjectClass() & getClassClass() 999
cache getStringClass() 943
cache getBooleanClass() 885
cache getVoidClass() 625
cache getEnumClass() 624
cache getByteClass() & getCharacterClass() 513
cache float, double, integer 372
cache long, short 299
make getIntegerClass() available in Commentable interface and use this in FieldDecider 294

Only the last modification required to change the Commentable interface. All other improvements have been done in the implementation only.

Potentiall NullPointerException in TypeParameterImpl#getBoundType()

Code containing an annotation, with the annotation implementation not available to the parser can result in a NullPointerException.

In the method TypeParameterImpl getBoundType(), Line 421 of /org.emftext.language.java/src-gen/org/emftext/language/java/generics/impl/TypeParameterImpl.java
(sorry code is not in GitHub, so not directly referenceable, the

((org.emftext.language.java.types.TypedElement)elementReference.getTarget()).getTypeReference()

might return null.

The rest of the code is only executed when argumentType is not null. So the code here can be easily modified without unwanted effects when a null check for the code mentioned above is introduced.

LocationMap is empty before selecting elements in the editor but populated afterwards

It's hard to describe it as JaMoPP-specific as possible.
Refactory hooks in when some one right-clicks in an open editor. The current selection is determined with the EMFTextEditorConnector. The connector calls locationMap.getElementsAt(..). The problem for JaMoPP is that this map is empty while right-clicking in the editor (selecting some elements). But the map is populated after the call to locationMap.getElementsAt(..). It seems that the workflow is a little bit distinct to other EMFText-generated languages. @jjohannes, can something be done here?

Parsing looses original ResourceSet JavaOptions settings.

In the JavaParser, the parse methods such as parse_org_emftext_language_java_annotations_AnnotationAttributeSetting() creates new model elements such as

element = org.emftext.language.java.annotations.AnnotationsFactory.eINSTANCE.createAnnotationAttributeSetting();

These elements are not associated with the original resource set.

As a result, during the downstream parsing, the new default resource set associated to those elements does not have the original ResourceSet options set such as to disable the layout information processing. This prevents to disable layout or location map processings for performance gains.

To reproduce this issue, initialize your resource set with a disabled Layout processing:

ResourceSet rs = new ResourceSetImpl();
Map<Object, Object> options = rs.getLoadOptions();
options.put(IJavaOptions.DISABLE_LAYOUT_INFORMATION_RECORDING, Boolean.TRUE);
options.put(IJavaOptions.DISABLE_LOCATION_MAP, Boolean.TRUE);

set a breakpoint in JavaANTLRParserBase.retrieveLayoutInformation() after the disableLayoutRecording check:

    protected void retrieveLayoutInformation(org.eclipse.emf.ecore.EObject element, org.emftext.language.java.resource.java.grammar.JavaSyntaxElement syntaxElement, Object object, boolean ignoreTokensAfterLastVisibleToken) {
  if (disableLayoutRecording || element == null) {
    return;
  }
  // set breakpoint here

Run your test app in debug mode and the debugger will stop because of disableLayoutRecording set to false.

disableLayoutRecording is set during JavaANTLRParserBase.setOptions() only.
If you follow the call stack in the debugger, you will notice a ResourceSet with default loadOptions set only.

Documentation for getting started

Hello everyone,

I would like to start using JaMoPP to generate an Ecore Model from existing Java-Code and eventually be able to write changes done to that model back into the Java source code.

The website seems to be down for me, so I dont know how to get any information/tutorials on how to start doing that. I currently have downloaded JaMoPP 1.4 via the Eclipse Market Place, restarted Eclipse but do not know what to do now at all - I do not even see anything having changed in my Eclipse, cannot find any new context menu entries etc., so I dont have any idea on how to start getting towards my goal of extracting a model from a Java Project to then propagate changes back to the code made to that model.

Could anyone help me out and provide me with some basic documentation/How-To's/Beginner tutorials of some sort?

Thank you very much.

JavaParser.addExpectedElement() - JavaContainmentTrace instantiation

Background

Inside the JavaParser, the addExpectedElement method is called quite often (>20.000 times). With a case study based on an ArgoUML example performed in context of the SPLevo / KoPL project, this method is called more the 141.5 billion times.

jamopp-method-hotspots-original

There seems to be no (obvious) way to reduce the number of invocation due to the parser logic because some parser status dependend processing is done in it. But there is also some data created that is neither status dependend nor modified later.
With each method invocation, an instance of JavaContainmentTrace is created which is an opportunity the caching.

Information Gathered from Code Review

In the original state of the code, the addExpectedElement method receives an eClass and an array of integers.

First: Investigating more in how the method is called, this array is always derieved from a static array

org.emftext.language.java.resource.java.mopp.JavaExpectationConstants.EXPECTATIONS[]

Changing the method signature, to receive the index of the Expectations array and solve the reference inside of addExpectedElement() allows for a better cache design.

Second: Investigating further in the dependence between the Expectations array and the provided eClass, there is a 1:1 relationship between those two. The EClass can be derived from the logic implemented for the static data build up inside addExpectedElement(), more specific from the data provided by JavaContainedFeature / JavaFollowSetProvider.
This constellation further allows for easier cache design and to remove the eClass attribute of the addExpectedElement() method.

Adapt Method Calls

Based on Eclipse's regular-expression-based search and replace perform the following replace all invocations:

Search for: org.emftext.language.java.resource.java.mopp.JavaExpectationConstants.EXPECTATIONS\[([0-9]*)\]\);
Replace with: $1\);

Search for: addExpectedElement\(([a-zA-Z\.\_]*\(\)\,) ([0-9]*)\);
Replace with: addExpectedElement($2);

Search for: addExpectedElement\(null, ([0-9]*)\);
Replace with: addExpectedElement($1);

Change method signature to public void addExpectedElement(int expectationId).
Add statement int[] ids = JavaExpectationConstants.EXPECTATIONS[expectationId]; after the if() configuration check

ContainmentTraceCache

A cache to statically initialize all containmentTrace objects needed during processing.
Based on the observations described above, the pre-initialized JavaContainmentTrace instances can be cached and received based on the expectationId only. This is done with a statically initialized LinkedHashMap. As an alternative, Google Guava Caching could be used but would require an additional dependency for JaMoPP.

As a result, only as much instances of JavaContainmentTrace objects are required as the EXPECTATIONS specification array has entries (~21k) and not as often the as JavaParser.addExpectedElement() is invoked during runtime (>141 billion in the case study)

Add support for Java7 constructs

Hi again,

i have another problem. If i initialize a Map or a List using the new-operator in a source file i got no template of my file. It doesn´t matter if i initialize this in a method taged by @CommentTamplate nor another method or in the top of my source-class.

regards

Dennis

error when run atl uml2atl

I see atl has changed and different from content on website. When I build atl file, it generate class with incorrect class structure:
class Address {
protected //@classifiers[name='List'] contact;
}

Please help urgent

IJavaOptions handling in JavaResource

The methods JavaResource.isLocationMapEnabled()and JavaResource.isLayoutInformationRecordingEnabled() do only check if the accoreding IJavaOptions are set, not what there concrete values are.

This must be changed for example from

protected boolean isLocationMapEnabled() {
  if (loadOptions == null) {
    return true;
  }
  return !loadOptions.containsKey(org.emftext.language.java.resource.java.IJavaOptions.DISABLE_LOCATION_MAP);
}

to

protected boolean isLocationMapEnabled() {
  if (loadOptions == null) {
    return true;
  }
  return !loadOptions.containsKey(org.emftext.language.java.resource.java.IJavaOptions.DISABLE_LOCATION_MAP)
    || loadOptions.get(org.emftext.language.java.resource.java.IJavaOptions.DISABLE_LOCATION_MAP) == Boolean.FALSE;
}

Because JavaResource is fully generated by EMF Text, the prefered solution would be to adapt the generator.

Reduce Resolver Related Class-Instances

Issue Description

The resolver logic is structured into several classes for better seperation of concerns. However, there are more instances of those classes created as necessary.

Code Review Results

JavaDefaultResolverDelegate

  • is used by the IJavaReferenceResolver implementations (e.g. AnnotationAttributeSettingAttributeReferenceResolver)
    They use the deResolve() method only which is thread safe, stateless and process submitted call arguments only.
    => It is an option to let all of them use only a single static instance

IJavaReferenceResolver

The different IJavaReferenceResolver implementations are instantiated by the JavaReferenceResolverSwitch only.
They are all stateless, and all of their setOptions() methods do nothing.
=> All JavaReferenceResolverSwitch instances could use the same resolver instances.

JavaReferenceResolverSwitch

As mentioned before, the resolver in the switch are stateless. The switch's setOptions()-method delegates the options map to the setOptions()-method of the resolvers, which again do nothing.
=> A single instance of the switch would be fine for the whole JaMoPP instance.
=> Within JaMoPP, there are 6 locations creating JavaReferenceResolverSwitch instances. (See screenshot below).
jamopp-javareferenceresolverswitch-instantiations

Recommended Adaptation

The locations within the src-gen source directory make all use of the JavaMetaInformation class, which already located in the manually modified source directory. Only JavaResource does create a new switch on it's own. Instead of the JavaResource itself, the JavaSourceOrClassFileResource is used, which is located in java.resource manually adapted source directory.
This allows to modify all 6 locations at already not-generated code locations.

To reduce the instantiation overhead and the memory footprint, these 6 locations should be adapted to request the switch from a factory using the same thread safe singleton.

Optimization Results

With the ArgoUML case study from the SPLevo/KoPL project, for example, the number of delegate instances has been reduced from > 450k (continuously increasing while the case study could not be finished) to 7 constant instances.
Also the switches and Resolvers have been reduced to constant number.

NullPointerException in JavaClasspath.registerClassifier()

From time to time, I receive a NullpointerException during JavaClasspath initialization (See stack trace below).

I use the following code to initialize a ResourceSet and an assigned JavaClasspath:

ResourceSet targetResourceSet = setUpResourceSet();
JavaClasspath cp = JavaClasspath.get(targetResourceSet);

with setUpRessourceSet() implemented as

    /**
     * Setup the JaMoPP resource set and prepare the parsing options for the java resource type.
     *
     * @return The initialized resource set.
     */
    private ResourceSet setUpResourceSet() {
        ResourceSet rs = new ResourceSetImpl();
        Map<Object, Object> options = rs.getLoadOptions();
        options.put(IJavaOptions.DISABLE_LAYOUT_INFORMATION_RECORDING, Boolean.FALSE);
        options.put(IJavaOptions.DISABLE_LOCATION_MAP, Boolean.FALSE);
        EPackage.Registry.INSTANCE.put("http://www.emftext.org/java", JavaPackage.eINSTANCE);

        Map<String, Object> factoryMap = rs.getResourceFactoryRegistry().getExtensionToFactoryMap();
        factoryMap.put("java", new JavaSourceOrClassFileResourceFactoryImpl());
        factoryMap.put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl());
        return rs;
    }

The code is part of an Eclipse plugin. I run it within an Eclipse instance. Unfortunately, it does not occure everytime and restarting the Eclipse test instance solves the issue in most cases.

Is there anything wrong in how the RessourceSet and the classpath are initialized?

Thanks
Benjamin

Stacktrace:

Caused by: java.lang.NullPointerException
    at org.eclipse.emf.common.util.BasicEMap.grow(BasicEMap.java:1487)
    at org.eclipse.emf.common.util.BasicEMap.doPut(BasicEMap.java:603)
    at org.eclipse.emf.common.util.BasicEMap$1.didAdd(BasicEMap.java:150)
    at org.eclipse.emf.common.util.BasicEMap$1.didAdd(BasicEMap.java:1)
    at org.eclipse.emf.common.util.BasicEList.addUnique(BasicEList.java:419)
    at org.eclipse.emf.common.util.AbstractEList.add(AbstractEList.java:301)
    at org.eclipse.emf.common.util.BasicEMap.put(BasicEMap.java:585)
    at org.eclipse.emf.common.util.BasicEMap$DelegatingMap.put(BasicEMap.java:793)
    at org.emftext.language.java.JavaClasspath.registerClassifier(JavaClasspath.java:515)
    at org.emftext.language.java.JavaClasspath.registerClassifierJar(JavaClasspath.java:414)
    at org.emftext.language.java.JavaClasspath.registerClassifierJar(JavaClasspath.java:378)
    at org.emftext.language.java.JavaClasspath.registerStdLib(JavaClasspath.java:366)
    at org.emftext.language.java.JavaClasspath.get(JavaClasspath.java:194)
    at org.emftext.language.java.JavaClasspath.get(JavaClasspath.java:272)
    at org.splevo.jamopp.extraction.JaMoPPSoftwareModelExtractor.extractSoftwareModel(JaMoPPSoftwareModelExtractor.java:51)

Make JavaLayoutUtil a static Utility

The JavaLayoutUtil class is a pure utility class. All methods are stateless and threadsafe.

In the current implementation, it is instantiated twice per resource. Once as private field in JavaSourceOrClassFileResource and once in the parent class JavaResource.

It would be better to follow the typical design of utility classes:

  • make the class final
  • make the constructor private
  • make the methods static
  • let the consumers call the static methods and not initializing any instances of JavaResource

While JavaSourceOrClassFileResource is a manually maintained class, JavaResource is generated by EMF Text an moving it into the manually maintained source folder is not a reasonable change.

The EMF Text code generation should be adapted to generate JavaLayoutUtil as a real utility class and generate JavaResource in such a way that it makes use of the static utlity methods.
I did identify the Utility class generator in EMF Text but not the generator for the concrete resource generator. So I hope the issue will find it's way when I leave it here.

Reducing JavaDefaultNameProvider instances

Current Implementation

Each instance of JavaDefaultResolverDelegate indirectly instantiates a new JavaDefaultNameProvider as an instance of a IJavaNameProvider by calling JavaMetaInformation.createNameProvider(). While the delegate uses a single instance of JavaMetaInformation, a new instance of the JavaDefaultNameProvider is created in the createNameProvider() method.

With the ArgoUML based case study performed in the SPLevo / KoPL project, this leads to more then 400,000 not necessary instances of this class. (Note, the JProfiler screenshot provided below is made during the processing. The final result is not possible at the time of writing, because JaMoPP does not finish in a reasonable time yet.

jamopp-profiling-javadefaultnameprovider-instances

Code Review Results

IJavaNameProvider provides only the method getNames(), and JavaDefaultNameProvider's implementation is status-independend, threadsafe and does not require a fresh instance with for every JavaDefaultResolverDelegate, or even with each call to JavaMetaInformation.createNameProvider()

Recommended Refactoring

A lightweight refactoring to prevent the creation of all these unnecessary instances is to change the createNameProvider() method to always return the same JavaDefaultResolverDelegate instance with each create call.

How to reference existing classes?

Hi

I'm writing a QVTo transformation from UML into Java code. Here is a fragment:

    object cu : JAVA::containers::CompilationUnit {
        name := self.name;
        classifiers := c;
        imports += object JAVA::imports::ClassifierImport {
            classifier := object JAVA::classifiers::Class {
                name := 'ArrayList';
            };
            namespaces := Sequence{'java', 'util'};
        };
    };

The problem is that the new instance of JAVA::classifiers::Class is created. How can I reference existing java.util.ArrayList class?

I've found the following example (http://www.reuseware.org/index.php/EMFText_JaMoPP_Applications_ATL)

java!Package.allInstances()->any(p | p.name = 'java.lang').compilationUnits->collect(
            cu | cu.classifiers)->flatten()->any(c | c.name = 'LinkedList')

But in QVTo JAVA::containers::Package.allInstances() returns nothing.

And also I've found a one more example (org.emftext.language.java.examples/uml2java/uml2java.atl)

    typeRef1 : java!ClassifierReference (
        target <- umlProperty.correctType(true),
        typeArguments <- if (umlProperty.upper = 1) then
                Sequence{}
            else
                Sequence{typeArgument}
            endif
    ),


helper context uml!Element def: correctType(outerType : Boolean) : java!Classifier = 
     if (self.type = OclUndefined)  then OclUndefined else
     if (self.upper <> 1 and outerType)  then java!Commentable.allInstances()->first().getConcreteClassifier('java.util.List') else     
     if (self.type.name = 'String') then java!Commentable.allInstances()->first().getStringClass() else
     self.type 
     endif endif endif;

The target Java model is empty. It doesn't contain any instances.

Thanks!

Project website is down

The project website jamopp.org seems to be down at the moment.
Opening jamopp.org currently returns:

Forbidden

You don't have permission to access / on this server.

Suppress layout information in outline

Since the layout information are "only" utility concepts they are annoying in the outline. It is too much of them being displayed.
I never integrated the LayoutInformation (LI) DSL into any of my projects but I assume that LI should be suppressed by default while generating the outline.

Reduce JavaContextDependentURIFragmentFactory Instances

Background

Currently, everytime a JavaContextDependentURIFragmentFactory is required a new instance is created in the JaMoPP code.
This leads to a new Factory for each URIFragement during code parsing.

A code review showd that the typed JavaContextDependentURIFragmentFactory is thread safe due to it's stateless processing.
A single instance per type could be used.

JavaParser

In the current implementation, new instances are created for each method call, for example of the parse methods of the JavaParser.

For example in parse_org_emftext_language_java_annotations_AnnotationAttributeSetting() each method invocation creates a new JavaContextDependentURIFragmentFactory instance:

registerContextDependentProxy(new org.emftext.language.java.resource.java.mopp.JavaContextDependentURIFragmentFactory<org.emftext.language.java.annotations.AnnotationAttributeSetting, org.emftext.language.java.members.InterfaceMethod>(getReferenceResolverSwitch() == null ? null : getReferenceResolverSwitch().getAnnotationAttributeSettingAttributeReferenceResolver()), element, (org.eclipse.emf.ecore.EReference) element.eClass().getEStructuralFeature(org.emftext.language.java.annotations.AnnotationsPackage.ANNOTATION_ATTRIBUTE_SETTING__ATTRIBUTE), resolved, proxy);

The typed JavaContextDependentURIFragmentFactory is always the same for a specific parse method and could be instantiated per JavaParser instance.

getReferenceResolverSwitch() always return the same switch instance provided by the metaInformation which is not null and the same for each ParserInstance. (see #16)
This allows to simplify the instantiation of the typed JavaContextDependentURIFragmentFactory per JavaParser instance.

JavaContextDependentURIFragmentFactory

Another code location instantiating JavaContextDependentURIFragmentFactory instances is in JavaResourcePostProcessor.
This can also be optimized by using a single instance of this factory per JavaResourcePostProcessor instance.

Optimization Result

The modifications lead to a static number of factory instances, independend of the number of processed java elements.
With the ArgoUML SPLevo/KoPL case study, this is more than 0.5 billion object instances (increasing, total number not available because parsing not possible yet).

Support Parsing Java Libraries Compiled With Java 8

It is not possible to parse Java libraries compiled with Java 8. This is problematic because Java 7 is not updated anymore. An upgrade to Java 8 is required.

The cause of the problem is the insufficient Java 8 support of the Apache BCEL library version that you use. The issue BCEL173 has already been solved for BCEL 6.0. Unfortunately, BCEL 6.0 is neither released nor announced to be released yet.

You might try the bcel-findbugs library instead, which has been suggest in the issue mentioned above for the time until BCEL 6.0 is released.

[CommentTemplate] Issue with JavaDoc comments

Hi,

i read your article about "commentTemplate" in the new Javamagazin. Nice work, exactly what i need.
I found out that if i tagged a method with a @CommentTemplate-Annotation and wrote in top of the method a javadoc comment i got no auto generated class of my source class.
If i delete the comment i got one.
Exists a workaround for that problem?

Dennis Grewe

M2M transformation - Trouble generating Java code

I am having trouble generating Java code with JaMoPP, given my sample
model transformation output file, as input for the code generation.

I have looked though and ran the sample ATL project on the
DevBoost JaMoPP Github repository and I see it produces the src-gen
folder and an empty java file. When I use similar run configuration
settings for my project I only obtain an empty java file.

I had also looked through a basic tutorial on running JaMoPP from:
primordion.com/Xholon/wiki/JaMoPP_Basic_Tutorial/
http://primordion.com/Xholon/wiki/JaMoPP_Basic_Tutorial/
On running the given code with my project specific files and I get errors at the point where the Java file is to be created.

Given the above I hope you can assist me with the following:

  1. Is there any detailed documentation on how to run the JaMoPP ATL
    sample project?
  2. Are there any other resources that have more detail on how to
    generate code with JaMoPP from a model transformation?

getObjectClass() returns a new Class instance without equals support

To test a Class element if it represents the java.lang.Object is not supported using the getObjectClass() and the equals method.

getObjectClass() always returns a new instance and the equals() method is not implemented for ClassImpl or ConcreteClassifier.

For example, the following code always returns false, even if the super class of the submitted class is the class java.lang.Object:

public boolean compareClasses(Class class){
Class objectClass = class.getObjectClass();
return(objectClass.equals(class.getSuperClass()));
}

Either the code should always return the same instance for a specific class, or the equals method should be implemented specific to the java meta model element.

JavaGrammarInformationProvider performance issue

The class JavaGrammarInformationProvider contains two methods ("getSyntaxElementID" and "getSyntaxElementByID") called quite often during parsing.
jamopp-performance-method-count

They use reflection to always look up an id or object in the same set of static and final fields within the JavaGrammarInformationProvider.

This can be considerably reduced by using a statically initialized cache for this limited set of values.

The JavaGrammarInformationProvider is an EMFText generated class located in
/org.emftext.language.java.resource.java/src-gen/org/emftext/language/java/resource/java/grammar/JavaGrammarInformationProvider.java
I did not figure out yet how to commit the requried change through a pull request. So please find below the required code changes for a cache using Java native LinkedHashMaps. An alternative would be a cache e.g. based on Google Guava, but this would require an additional dependency for the o.e.l.java.resource.java plugin.

Original Code

    public static String getSyntaxElementID(org.emftext.language.java.resource.java.grammar.JavaSyntaxElement syntaxElement) {
        if (syntaxElement == null) {
            // null indicates EOF
            return "<EOF>";
        }
        for (java.lang.reflect.Field field : org.emftext.language.java.resource.java.grammar.JavaGrammarInformationProvider.class.getFields()) {
            Object fieldValue;
            try {
                fieldValue = field.get(null);
                if (fieldValue == syntaxElement) {
                    String id = field.getName();
                    return id;
                }
            } catch (Exception e) { }
        }
        return null;
    }

    public static org.emftext.language.java.resource.java.grammar.JavaSyntaxElement getSyntaxElementByID(String syntaxElementID) {
        try {
            return (org.emftext.language.java.resource.java.grammar.JavaSyntaxElement) org.emftext.language.java.resource.java.grammar.JavaGrammarInformationProvider.class.getField(syntaxElementID).get(null);
        } catch (Exception e) {
            return null;
        }
    }

Modified Version using local caches

    /** A statically pre-loaded cache to speed up the syntax element id look up. */
    private static LinkedHashMap<JavaSyntaxElement, String> syntaxElementIDCache = new LinkedHashMap<JavaSyntaxElement, String>();

    /** A statically pre-loaded cache to speed up the syntax element look up. */
    private static LinkedHashMap<String, JavaSyntaxElement> syntaxElementCache = new LinkedHashMap<String, JavaSyntaxElement>();

    /** Preload the caches */
    static {
        syntaxElementIDCache.put(null, "<EOF>");
        for (java.lang.reflect.Field field : org.emftext.language.java.resource.java.grammar.JavaGrammarInformationProvider.class.getFields()) {
            Object fieldValue = field.get(null);
            syntaxElementIDCache.put((JavaSyntaxElement) fieldValue, field.getName());
            syntaxElementCache.put(field.getName(), (JavaSyntaxElement) fieldValue);
        }
    }

    public static String getSyntaxElementID(JavaSyntaxElement syntaxElement) {
        return syntaxElementIDCache.get(syntaxElement);
    }

    public static JavaSyntaxElement getSyntaxElementByID(String syntaxElementID) {
        return syntaxElementCache.get(syntaxElementID);
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.