Compare two source code files using EMF models - java

In my application I should compare two source code files to see if something has changed and then highlight those changes. For that i thought of using EMF compare. My application is a standalone application and is not used as a plugin or something similar. It should run without eclipse. Therefore I linked all the necessary libraries and tried to use EMF compare.
The problem now is that I donĀ“t know how to build the two models that I have to use to compare the two source code files against each other. In the following code snippet I wrote as a first approach, the source code files are passed as files (Test1.java and Test2.java) but actually the source code of both files are stored in a string as the method parameters indicate.
So my question is basically how can I generate two models based on String that contain Java source code so that I can use these two models to compare against each other?
public void compare(String source1, String source2) throws IOException, InterruptedException {
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("java", new ResourceFactoryImpl());
XSDEcoreBuilder builder = new XSDEcoreBuilder();
Collection<EObject> model1 = builder.generate(URI.createFileURI("Test1.java"));
Collection<EObject> model2 = builder.generate(URI.createFileURI("Test2.java"));
final MatchModel match = MatchService.doMatch(model1.iterator().next(), model2.iterator().next(), Collections.<String, Object> emptyMap());
final DiffModel diff = DiffService.doDiff(match, false);
final List<DiffElement> differences = new ArrayList<DiffElement>(diff.getOwnedElements());
System.out.println("MatchModel :\n");
System.out.println(ModelUtils.serialize(match));
System.out.println("DiffModel :\n");
System.out.println(ModelUtils.serialize(diff));
}

You can use Java metamodel from Modisco project, I think.
With it you can deserialize java files into EMF model and then compare.
EMFText project also has Java model implementation.
Give 'em a try!

I think you are using the wrong technology here. AFAIK, EMF doesn't support a parser generator that you could use to parse Java source code and build parse trees as EMF models.
IMO, a better idea would be to use one of the existing Java parser generators (ANTLR, JavaCC, etc) and an existing Java grammar, then implement your comparison based on the parse trees that the generated parser produces.

Related

Papyrus (Eclipse) - How to generate diagrams by code?

I need to generate a Diagram for Papyrus (Eclipse neon) by Code, but on the networx I cant't find any explaination about creating diagrams by code except for BDD.
My actual situation is the following:
I receive a .csv file containing some information written like "Element A , Connection Type , Element B"
What I need to do is to generate a diagram representing them as following:
Diagram Example :
NOTE: I'm not interested in representing colours in the final product
So My questions are:
Which diagram from Papyrus should I use to achieve this? (I must use Papyrus)
Can someone provide me some documentation to generate it by code?
I found this post on Eclipse community: https://www.eclipse.org/forums/index.php/m/1708054/?srch=activity+diagram+programmatically#msg_1708054
But It seems there's no class "CreateActivityDiagramCommand" containing the command to generate the diagram.
Please don't try to understand the sense of representing information like that, just help me creating a diagram to do that.
SOLVED:
I found a way to draw an Activity Diagram programmatically, since I need only rectangles containig a simple string and arrows it wasn't difficult to draw.
Navigating into Papyrus Source code I found a package org.eclipse.papyrus.uml.diagram.activity containing the CreateActivityDiagramCommand Class so I added that to dependancies and I started building my method to generate a Diagram
If anyone is interested I did as Following:
public static Diagram createActivityDiagram(EObject owner, String name) //owner is an UML Package
{
ModelSet modelSet = null;
ResourceSet resourceSet = owner.eResource().getResourceSet();
if (resourceSet instanceof ModelSet)
modelSet = (ModelSet) resourceSet;
else
return null;
Diagram diagram;
CreateActivityDiagramCommand creatediagramCommand = new CreateActivityDiagramCommand();
diagram = creatediagramCommand.createDiagram(modelSet, owner, name);
return diagram;
}

EMF model comparison with EMF Compare

I have two versions of the EMF instances that are based on the same ecore model. I need to prepare a list of things that changed from v1 to v2 in the following format
For each object in the model
Object Name:
Modified Attributes:
Added Attributes:
Deleted Attributes:
Each of these emf instance files are actually a representation of the DB data. User doesn't directly change the DB but they change the emf instance file. The tool need to identify these changes and then need to generate the necessary DML statements. Appreciate if a pseudo code can be presented on how to achieve this or is there a better alternative. Below is the code I currently have
public Comparison compare()
{
// Load the two input models
ResourceSet resourceSet1 = new ResourceSetImpl();
ResourceSet resourceSet2 = new ResourceSetImpl();
String xmi1 = "src/test/java/com/equifax/ic/provisioning/service/v1.xmi";
String xmi2 = "src/test/java/com/equifax/ic/provisioning/service/v2.xmi";
load(xmi1, resourceSet1);
load(xmi2, resourceSet2);
// Configure EMF Compare
EMFCompare comparator = EMFCompare.builder().build();
// Compare the two models
IComparisonScope scope = EMFCompare.createDefaultScope(resourceSet1, resourceSet2);
return comparator.compare(scope);
}
#Test
public void testCompare()
{
Comparison comparison = compare();
List<Diff> differences = comparison.getDifferences();
for(Diff d: differences)
{
System.err.println("d.getKind(): "+d.getKind());
System.err.println("d.getMatch(): " + d.getMatch());
System.err.println("State: " + d.getState());
}
assertSame(Integer.valueOf(12), Integer.valueOf(differences.size()));
}
Output
d.getKind(): ADD
d.getMatch(): MatchSpec{left=BillableSystemEvent#1b5340c Application Processed, right=BillableSystemEvent#16c163f Application Processed, origin=<null>, #differences=2, #submatches=2}
State: UNRESOLVED
d.getKind(): DELETE
d.getMatch(): MatchSpec{left=BillableSystemEvent#1b5340c Application Processed, right=BillableSystemEvent#16c163f Application Processed, origin=<null>, #differences=2, #submatches=2}
State: UNRESOLVED
I cannot say I really understand everything you're trying to achieve, but as I understand it, you are not really interested in the format EMF Compare uses for its differences. Rather, you are trying to generate a differente kind of representation for the diffs.
You might be interested in just reimplementing an IDiffProcessor. Diff processors are notified every time we detect a change. By default we create our "Diff" instances... Nothing prevents you from generating DML statements instead. You can get a quick overview of the IDiffProcessor API here.

Generating BPEL files programmatically?

Is there a way to generate BPEL programmatically in Java?
I tried using the BPEL Eclipse Designer API to write this code:
Process process = null;
try {
Resource.Factory.Registry reg =Resource.Factory.Registry.INSTANCE;
Map<String, Object> m = reg.getExtensionToFactoryMap();
m.put("bpel", new BPELResourceFactoryImpl());//it works with XMLResourceFactoryImpl()
//create resource
URI uri =URI.createFileURI("myBPEL2.bpel");
ResourceSet rSet = new ResourceSetImpl();
Resource bpelResource = rSet.createResource(uri);
//create/populate process
process = BPELFactory.eINSTANCE.createProcess();
process.setName("myBPEL");
Sequence mySeq = BPELFactory.eINSTANCE.createSequence();
mySeq.setName("mainSequence");
process.setActivity(mySeq);
//save resource
bpelResource.getContents().add(process);
Map<String,String> map= new HashMap<String, String>();
map.put("bpel", "http://docs.oasis-open.org/wsbpel/2.0/process/executable");
map.put("tns", "http://matrix.bpelprocess");
map.put("xsd", "http://www.w3.org/2001/XMLSchema");
bpelResource.save(map);
}
catch (Exception e) {
e.printStackTrace();
}
}
but I received an error:
INamespaceMap cannot be attached to an eObject ...
I read this message by Simon:
I understand that using the BPEL model outside of eclipse might be desirable, but it was never intended by us. Thus, this isn't supported
Is there any other API that can help?
You might want to give JAXB a try. It helps you to transform the official BPEL XSD into Java classes. You use those classes to construct your BPEL document and output it.
I had exactly the same problem with the BPELUnit [1], so I started a module in BPELUnit that has the first things necessary for generating and reading BPEL Models [2] although it is far from complete. Supported is only BPEL 2.0 (1.1 will follow later) and handlers are also currently not supported (but will be added). It is under active development because BPELUnit's code coverage component will be based on it so it will get BPEL-feature complete over time. You are happily invited to contribute if you need to close gaps earlier.
You can check it out from GitHub or grap the Maven artifact.
As of now there is no documentation but you can have a look at the JUnit tests that read and write processes.
If this is not suitable for, I'd like to share some experiences with you:
Do not use JAXB: You will need to read and write XML Namespaces which are not preserved with JAXB. That's why I have chosen XMLBeans. DOM would be the other alternative that I can think of.
The inheritance in the XML Schema is not really developer friendly. That's why there are own interface structures and wrappers around the XMLBeans generated classes.
Daniel
[1] http://www.bpelunit.net
[2] https://github.com/bpelunit/bpelunit/tree/master/net.bpelunit.model.bpel
This has been solved using the unify framework API after adding the necessary classes to handle correlation. BPELUnit stated by #Daniel seems to be another alternative.
The Eclipse BPEL API is based on an EMF Model. So you could generate your own artifacts using JET or Xpand based on that. This way there is no requirement to run inside Eclipse.
Although you may can't use BPEL outside of Eclipse, have you considered moving parts of your application inside it?
The BPEL XML Schemas are listed in the appendig of the spec. So you could also base your work on that and integrate with existing BPEL applications where necessary.
In case anyone is looking to solve the above problem while still running inside eclipse environment.
The problem can be resolved as stated by Luca Pino here by adding:
AdapterRegistry.INSTANCE.registerAdapterFactory( BPELPackage.eINSTANCE, BasicBPELAdapterFactory.INSTANCE );
before the resource creation line i.e.
Resource bpelResource = rSet.createResource(uri);
Note: Another solution, to the same problem, also stating how to resolve the dependencies to make this code work, can be found in my other answer here.

Unable to incorporate Eclispe JDT codeAssist facilities outside a Plug-in

Using Eclipse jdt facilities, you can traverse the AST of java code snippets as follows:
ASTParser ASTparser = ASTParser.newParser(AST.JLS3);
ASTparser.setSource("package x;class X{}".toCharArray());
ASTparser.createAST(null).accept(...);
But when trying to perform code complete & code selection it seems that I have to do it in a plug-in application since I have to write codes like
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(somePath));
ICodeAssist i = JavaCore.createCompilationUnitFrom(f);
i.codeComplete/codeSelect(...)
Is there anyway that I can finally get a stand-alone java application which incorporates the jdt code complete/select facilities?
thx a lot!
shi kui
I have noticed it that using org.eclipse.jdt.internal.codeassist.complete.CompletionParser
I can parse a code snippet as well.
CompletionParser parser =new CompletionParser(new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
new CompilerOptions(null),
new DefaultProblemFactory(Locale.getDefault())),
false);
org.eclipse.jdt.internal.compiler.batch.CompilationUnit sourceUnit =
new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
"class T{f(){new T().=1;} \nint j;}".toCharArray(), "testName", null);
CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
CompilationUnitDeclaration unit = parser.dietParse(sourceUnit, compilationResult, 25);
But I have 2 questions:
1. How to retrive the assist information?
2. How can I specify class path or source path for the compiler to look up type/method/field information?
I don't think so, unless you provide your own implementation of ICodeAssist.
As the Performing code assist on Java code mentions, Elements that allow this manipulation should implement ICodeAssist.
There are two kinds of manipulation:
Code completion - compute the completion of a Java token.
Code selection - answer the Java element indicated by the selected text of a given offset and length.
In the Java model there are two elements that implement this interface: IClassFile and ICompilationUnit.
Code completion and code selection only answer results for a class file if it has attached source.
You could try opening a File outside of any workspace (like this FAQ), but the result wouldn't implement ICodeAssist.
So the IFile most of the time comes from a workspace location.

How to designate resources as do-not-translate?

I work on the localization of Java software, and my projects have both .properties files and XML resources. We currently use comments to instruct translators to not translate certain strings, but the problem with comments is that they are not machine-readable.
The only solution I can think of is to prefix each do-not-translate key with something like _DNT_ and train our translation tools to ignore these entries. Does anyone out there have a better idea?
Could you break the files up into ones to be translated or ones to be not translated and then only send them the one that are to be translated? (Don't know the structure so har dto know when answering if that is practical...)
The Eclipse JDT also uses comments to prevent the translation of certain Strings:
How to write Eclipse plug-ins for the international market
I think your translation tool should work in a similar way?
The simplest solution is to not put do-not-translate strings (DNTs) in your resource files.
.properties files don't offer much in the way of metadata handling, and since you don't need the data at runtime, its presence in .properties files would be a side-effect rather than something that is desirable. Consider too, partial DNTs where you have something that cannot be translated contained in a translatable string (e.g. a brand name or URI).
"IDENTIFIER english en en en" -> "french fr IDENTIFIER fr fr"
As far as I am aware, even standards like XLIFF do not take DNTs into consideration and you'll have to manage them through custom metadata files, terminology files and/or comments (such as the note element in XLIFF).
Like axelclk posted in his link... eclipse provide a
//$NON-NLS-1$
Statement to notify the project that the first string in this line should not translated. All other string you can find by calling
Source->Externalize Strings
External Strings include all languages you want to support.
File which include the translations looking like:
PluginPage.Error1 = text1
PluginPage.Error2 = text2
Class which read the translation
private static final String BUNDLE_NAME = "com.plugin.name"; //$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
private PluginMessages() {
}
public static String getString(String key) {
// TODO Auto-generated method stub
try {
return RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
And you can call it like:
String msg = PluginMessages.getString("PluginPage.Error2"); //$NON-NLS-1$
EDIT:
When a string is externalized and you want to use the original string, you can delete the externalize string from all properties files, without the default one. When the Bundle can not find a message file which is matching to the local language, the default is used.
But this is not working at runtime.
If you do decide to use do-not-translate comments in your properties files, I would recommend you follow the Eclipse convention. It's nothing special, but life will be easier if we all use the same magic string!
(Eclipse doesn't actually support DO-NOT-TRANSLATE comments yet, as far as I know, but Tennera Ant-Gettext has an implementation of the above scheme which is used when converting from resource bundles to Gettext PO files.)

Categories

Resources