Getting info from PsiMethod in Intellij IDEA plugin - java

I'm writing Intellij IDEA plugin for my project, and I've faced a problem - I cannot get some ingo about method (PsiMethod) from my code.
First, I want to know is this method public.
And second, I want to get fully-qualified names of the parameter classes. Currently I'm doing it like this:
method.getReturnTypeNoResolve().getInternalCanonicalText()
But it doesn't provide full name (with package name) for the standard JVM classes like String and List.
UPDATE First problem solved with the following code:
PsiUtil.getAccessLevel(method.getModifierList()) == PsiUtil.ACCESS_LEVEL_PUBLIC
But I still cannot get fully qualified class name
UPDATE 2 Here is the full listing of my code:
Project currentProject = DataKeys.PROJECT.getData(e.getDataContext());
PsiClass abstractComponentClass = JavaPsiFacade.getInstance(currentProject).findClass("com.mjolnirr.lib.component.AbstractComponent", GlobalSearchScope.allScope(currentProject));
TreeClassChooser result = TreeClassChooserFactory
.getInstance(currentProject)
.createInheritanceClassChooser("Choose the class to generate manifest",
GlobalSearchScope.projectScope(currentProject),
abstractComponentClass,
false,
false,
null);
result.showDialog();
PsiClass classToGenerate = result.getSelected();
List<ManifestMethod> methods = new ArrayList<ManifestMethod>();
for (PsiMethod method : classToGenerate.getAllMethods()) {
// If this method is inherited from the Object class we don't need it
if (isComponentInitialize(method)) {
continue;
}
List<ManifestParameter> parameters = new ArrayList<ManifestParameter>();
for (PsiParameter param : method.getParameterList().getParameters()) {
parameters.add(new ManifestParameter(param.getType().getCanonicalText().replaceAll("\\<.*?\\>", "")));
}
if (method.getReturnType() != null) {
ManifestMethod manifestMethod = new ManifestMethod(method.getName(),
method.getReturnTypeNoResolve().getInternalCanonicalText().replaceAll("\\<.*?\\>", ""),
parameters);
if (!methods.contains(manifestMethod) && isPublic(method)) {
System.out.println("->" + method.getReturnType().getCanonicalText());
methods.add(manifestMethod);
}
}
}

Solved - my test IDEA instance has wrong Java SDK connected.

Related

ContextUpdateHandler interface does not work for a specific context

I tried to catch a specific context/named graph by implementing following function of the ContextUpdateHandler interface:
#Override
public Resource[] getUpdateContexts() {
getLogger().info("getUpdateContexts");
Resource[] res = new Resource[2];
res[0] = () -> "";
res[1] = () -> "http://example.com/testGraph";
return res;
}
When I make an insert or delete to the default graph, it works perfectly and it gets me into the handleContextUpdate() method where I can further process the update request. However, when I do any insert or delete on a specific context, say http://example.com/testGraph, it does not get recognized. Do you know what might be the problem?
I also tried to write it like this: <http://example.com/testGraph> and it didnt work
These are my queries:
# Does not work.
delete data {
graph <http://example.com/testGraph> {
<http://example.com/s/deleteThis2>
<http://example.com/p/deleteThis2>
<http://example.com/o/deleteThis2> }
}
# Works perfectly fine.
delete data {
<http://example.com/s/deleteThis2>
<http://example.com/p/deleteThis2>
<http://example.com/o/deleteThis2>
}
Thanks!
Did you try res[1] = new SimpleIRI("http://example.com/testGraph");?
Or check the backend code for route differentials
And try adding / to path

Modifying of the Mwe2 workflow generated by Xtext programmatically

I'm running Mwe2 workflow programmatically and I need to add referencedResource for the Terminals.xtext to the GenerateYourDsl.mwe2 file in order to run this workflow successfully. Mentioned GenerateYourDsl.mwe2 file is generated by Xtext when I create new project - I didn't modify it.
Is it somehow possible to get object out of this workflow, access it in Java and add this one attribute to the language attribute of the component attribute of the workflow ?
Here's the workflow:
Workflow {
component = XtextGenerator {
configuration = {
project = StandardProjectConfig {
baseName = "org.example.yourdsl"
rootPath = rootPath
eclipsePlugin = {
enabled = true
}
createEclipseMetaData = true
}
code = {
encoding = "UTF-8"
lineDelimiter = "\n"
fileHeader = "/*\n * generated by Xtext \${version}\n */"
}
}
language = StandardLanguage {
name = "org.example.yourdsl.YourDsl"
fileExtensions = "yourdsl"
//following line needs to be added - in original generated workflow it is not
referencedResource = "platform:/resource/org.eclipse.xtext/org/eclipse/xtext/common/Terminals.xtext"
serializer = {
generateStub = false
}
validator = {
// composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
// Generates checks for #Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
generateDeprecationValidation = true
}
}
}
}
I'm generating projects programmatically (using CliProjectsCreator and WizardConfiguration) and need to run the workflow when the projects are generated in order to generate src, src-gen files etc. But as I'm trying to run it programmatically (not in Eclipse) and Terminals are used in my grammar, I'm getting this error:
XtextLinkingDiagnostic: null:1 Couldn't resolve reference to Grammar 'org.eclipse.xtext.common.Terminals'.
TransformationDiagnostic: null:36 Cannot create datatype WS. If this is supposed to return EString, make sure you have imported 'http://www.eclipse.org/emf/2002/Ecore' (ErrorCode: NoSuchTypeAvailable)
TransformationDiagnostic: null:39 Cannot create datatype NAME_TERMINAL. If this is supposed to return EString, make sure you have imported 'http://www.eclipse.org/emf/2002/Ecore' (ErrorCode: NoSuchTypeAvailable)
TransformationDiagnostic: null:42 Cannot create datatype VALUE_TERMINAL. If this is supposed to return EString, make sure you have imported 'http://www.eclipse.org/emf/2002/Ecore' (ErrorCode: NoSuchTypeAvailable)
there should be no need to add the terminals grammar explicitely. It should be found on the classpath via org.eclipse.xtext.resource.ClassloaderClasspathUriResolver.resolve(Object, URI) if the workflow is called with a proper classpath.
have a look what the wizard creates when selecting maven: a call to the maven exec plugin calling into Mwe2Launcher main with the proper classpath

Variables did not replaced

I wrote some code to replace variables in docx tamplate file header.
List<SectionWrapper> sectionWrappers = this.wordMLPackage.getDocumentModel().getSections();
for (SectionWrapper sw : sectionWrappers) {
HeaderFooterPolicy hfp = sw.getHeaderFooterPolicy();
HeaderPart defaultHP = hfp.getDefaultHeader();
if (defaultHP != null) {
defaultHP.variableReplace(getVariablesForChange());
if (hfp.getFirstHeader() != null) {
hfp.getFirstHeader().variableReplace(getVariablesForChange());
}
}
}
getVariablesForChange() is a Map has contains the variables and values.
When I running the unit test the replace is corectly fine but I use this in my web application on Tomee Plume the variables does not replaced.
For example the variable is: ${TOCHANGE} it looks like this after change TOCHANGE.
Docx4j version is: 3.3.6
Please help me to resolve this issue.
It won't work if your KEY is split across separate runs in your docx.
See https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/model/datastorage/migration/VariablePrepare.java

How to load 2 versions of the same Jar in 1 class Java

This is a complicated question but I will do my best to describe my problem.
I need to load 2 versions of the same JAR in a top level class (v1.jar and v2.jar) so I have access to both versions of the jar. The reason for this is because I want to test if any feature in v2.jar has regressed from v1.jar
In my top level class, I want to call methods of v1.jar and v2.jar and then validate the output from v1 against v2 output. This way I can be certain nothing got screwed up.
class Common {
// Names of the classes would be the same so not sure how I would invoke the classes from the 2 different jars?
String resultv1 = EngineV1.run("a","b","c");
String resultv2 = EngineV2.run("a","b","c");
Assert.equals(resultv1, resultv2, "Regression has been introduced...");
}
I can't import v1 and v2 jars as maven dependencies since this will create a version conflict in maven and by default maven will use the newest jar. So I thought about creating a common interface and having 2 different implementation classes of that interface. Then in the toplevel I can use class loaders to load v1 and v2 jars, etc. But this way not work since I would have to change production v1.jar to implement the common interface.
Any help or insight will be much appreciated. I'd very much like to see samples if possible. And please don't refer me to other threads
Your test class can set up a ClassLoader for each .jar file. The easiest way to do that, is to use URLClassLoader.
Example:
File jar1 = new File("/path/to/v1.jar");
File jar2 = new File("/path/to/v2.jar");
URLClassLoader v1Loader = URLClassLoader.newInstance(new URL[] { jar1.toURI().toURL() });
URLClassLoader v2Loader = URLClassLoader.newInstance(new URL[] { jar2.toURI().toURL() });
Class<?> engineClass1 = v1Loader.loadClass("org.example.Engine");
Class<?> engineClass2 = v2Loader.loadClass("org.example.Engine");
Method runMethod1 = engineClass1.getMethod("run");
Method runMethod2 = engineClass2.getMethod("run");
Object engine1 = engineClass1.newInstance();
Object engine2 = engineClass2.newInstance();
String result1 = (String) runMethod1.invoke(engine1);
String result2 = (String) runMethod2.invoke(engine2);
Note that since neither .jar file is on the classpath of the test code, the code cannot declare any variables of types from the .jar files. All access from test code must be done using reflection.
UPDATE
You might also need to change the context class loader when making the calls:
String result1, result2;
Thread thread = Thread.currentThread();
ClassLoader myLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(v1Loader);
result1 = (String) runMethod1.invoke(engine1);
thread.setContextClassLoader(v2Loader);
result2 = (String) runMethod2.invoke(engine2);
} finally {
thread.setContextClassLoader(myLoader);
}
// Compare result1 and result2
I found this from a different Stackoverflow question where I needed to load a jar during runtime
/*
* Adds the supplied Java Archive library to java.class.path. This is benign
* if the library is already loaded.
*/
public static synchronized void loadLibrary(java.io.File jar) throws Exception {
try {
/*We are using reflection here to circumvent encapsulation; addURL is not public*/
java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
java.net.URL url = jar.toURI().toURL();
/*Disallow if already loaded*/
for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
if (it.equals(url)){
return;
}
}
java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
method.setAccessible(true); /*promote the method to public access*/
method.invoke(loader, new Object[]{url});
} catch (final java.lang.NoSuchMethodException |
java.lang.IllegalAccessException |
java.net.MalformedURLException |
java.lang.reflect.InvocationTargetException e){
throw new Exception(e);
}
}
Works for my purposes

Orient DB - Export subclasses of a specified class using JAVA

Im working with exporting and importing Orient DB using java. I could export a whole database. But when i specify to export a specified class it export that class only. Sub classes are not exported. Here is the code:
ODatabaseDocumentTx db = new ODatabaseDocumentTx("remote:localhost/sampleDataBase").open("admin", "admin");
ODatabaseExport export = new ODatabaseExport(db, "DataCont/FinalTry.gz", listener);
Set<String> a= new HashSet<String>();
a.add("Employee".toUpperCase());
export.setIncludeClasses(a);
export.exportDatabase();
export.close();
So is this suppose to be or am i doing anything wrong?
Checking the source code for ODatabaseExport it does seem that it only takes clusters/records which are exactly of the type specified with setIncludeClasses(). For instance in exportRecords():
ODocument doc = (ODocument) rec;
final String className = doc.getClassName() != null ? doc.getClassName().toUpperCase() : null;
if (includeClasses != null) {
if (!includeClasses.contains(className))
continue;
} else if (excludeClasses != null) {
if (excludeClasses.contains(className))
continue;
}
They have similar checks in several other places in that class. This would mean that you need to put into the a set all the classes you want to export yourself.
You can add this piece of code if want to export all subclasses too:
Set<String> classesToExport = new HashSet<>();
classesToExport.add("Employee".toUpperCase());
OSchema oSchema = db.getMetadata().getSchema();
for (String className : classesToExport) {
OClass clazz = oSchema.getClass(className);
for(OClass subClass : clazz.getAllBaseClasses()){
//String subClassName = subClass.getName();
String subClassName = subClass.getName().toUpperCase();
if(!classesToExport.contains(subClassName)){
classesToExport.add(subClassName);
}
}
}

Categories