Closed mahesh-hegde closed 4 months ago
Since this is marked good first issue, here are the steps to solve this
In the summarizer java project, (jnigen/java
), look out for SummarizerOptions
class.
This class is being parsed from command line using Apache commons CLI, add factory (static) methods to obtain an instance of this class by parsing JSON, and another instance method to dump it back to JSON (for debugging purposes).
--read-config-from-stdin
in current fromCommandLine
factory constructor, which then constructs a SummarizerOptions
from stdin. Iterate and decide which is optimal design here.print SummarizerOptions
to stderr, because jnigen will print it when invocation fails. You may want to pretty-print this.
in summary
class, add a SummarizerOptions
class which is exact copy of this. Use json-serializable to serialize. (We are already using it for element types, so no need to add dependency).
in getSummary
make required adjustments.
Should this JSON be printed to log? If so, it must be on one line.
Remove current command invocation of summarizer vs. keep it and use another argument (or lack of argument?) to read from stdin.
Sir I wish to contribute on this one
Can you elaborate this point "This class is being parsed from command line using Apache commons CLI, add factory (static) methods to obtain an instance of this class by parsing JSON, and another instance method to dump it back to JSON (for debugging purposes)"
Do we have to parse "exampleClassSummary.json" return a object. And what is "dump it back to JSON", is it encoding new json file?
Can you elaborate this point
"This class is being parsed from command line using Apache commons CLI, add factory (static) methods to obtain an instance of this class by parsing JSON, and another instance method to dump it back to JSON (for debugging purposes)"
We have a Java part and a Dart part in this codebase. Java part (It's a maven project in jnigen/java
folder) parses the Java code we give to jnigen, and gives us a summary in JSON format. This part is called the summarizer
.
For this, we need to pass the various options. Like class-path
(where to find required java JARs), source-path
(where to find java files to parse) etc..
All of that is stored in SummarizerOptions
class.
So what we are doing now is, we invoke this summarizer as separate command, java -jar ApiSummarizer.jar
etc.. You can see this command in the logs of executing jnigen
.
What this issue is about: the command gets very long and cluttered if we pass everything as command option. So we want to read that from standard input System.in
.
For that, we need some structure. You might have done scanner.next()
etc.. when you're learning java. But here the input is complicated. So we have to read those options in JSON format.
If we read JSON, we can read all values it into SummarizerOptions
class directly, using Jackson-databind library. We already using that library.
The task is to modify the APISummarizer java code, and the dart code which calls it, so that instead of command options, we pass options in JSON format through System.in
(stdin of process on dart side).
Do we have to parse "exampleClassSummary.json" return a object. And what is "dump it back to JSON", is it encoding new json file?
You're probably looking at test file. If you're not familiar with pipes, json, serialization etc.. this might be hard (I know these aren't taught at universities properly). feel free to ask any question you get.
I had some doubts 1.Are we passing the options through the terminal or they are getting read from any dart file.Because you mentioned stdin of process on dart side
2.Which dart code is calling the Java code. I went through the setup.dart and jni.dart but couldn't find anything of Java.
I ran Main.java and saw all the commons.cli implementation with SummerizerOptions.java.
The term Standard input is being used very often.So far i know it means taking input from user through keyboard right?
Sure. That's a good start.
Are we passing the options through the terminal Standard input is being used very often
In any OS, Standard input
is an abstraction your program sees, input doesn't necessarily come from the terminal.
If you do echo "HI" | cat
in Linux Bash, there are 2 processes, (echo & cat), the output of first one will be passed to input of second. Like that, we can programmatically give input to any command.
And the inverse, we can programmatically invoke and read output of the command.
How is this possible? conceptually, input & output are just streams
just like any other file. If you create a process from your program (eg run a command), you can write to its input and read from its output. So we don't have to do that manually from terminal.
Which dart code is calling the Java code.
It's jnigen
that calls the JAR command.
Sir today I was trying to make a process object with start function and wanted to give stdin but i got file not found exception Although the file was in current working directory
when gave cat as exec and A file path through stdin it gave the error file not found
I don't quite understand what you're trying to do. Can you paste the code?
`import 'dart:io'; import 'dart:convert';
Future main() async { Process.start('cat', []).then((Process ps) { ps.stdout.transform(utf8.decoder).listen((event) { print('$event'); }); ps.stdin.write('C:\Users\Dell\IdeaProjects\Processpractice\myfile.txt');
Process.killPid(ps.pid); }); }`
when i cat command in powershell it asks for path[0] then i enter the path and it keeps on asking till i press enter two times i was trying to pass the file path through stdin but throws this exception
`Unhandled exception: ProcessException: The system cannot find the file specified.
Command: cat
dart-lang/jnigen#1 Process.start (dart:io-patch/process_patch.dart:38:20)
dart-lang/jnigen#2 main (file:///C:/Users/Dell/IdeaProjects/Processpractice/progprac.dart:5:11)
dart-lang/native#802 _delayEntrypointInvocation.
Process finished with exit code 255 `
And with run also I'm getting this
code:
var result = await Process.run('ls', ['c:\\Users\Dell']);
Exception: `Unhandled exception: ProcessException: The system cannot find the file specified.
Command: ls c:\UsersDell
dart-lang/jnigen#1 Process.start (dart:io-patch/process_patch.dart:38:20)
dart-lang/jnigen#2 _runNonInteractiveProcess (dart:io-patch/process_patch.dart:578:18)
dart-lang/native#802 Process.run (dart:io-patch/process_patch.dart:49:12)
dart-lang/jnigen#4 main (file:///C:/Users/Dell/IdeaProjects/Processpractice/progprac.dart:16:30)
dart-lang/native#803 _delayEntrypointInvocation.
Process finished with exit code 255 `
You shouldn't need stream listeners and all, in this particular case. It appears you're writing file name as the content, not the contents of file itself. So what you wrote doesn't include end of file delimiter or close the stdin, which means cat doesn't terminate.
For second one, it may be that you're escaping the path improperly, because '\D' should show you a warning anyway, or maybe because ls doesn't exist as executable on your specific windows machine.
If you don't understand the concept itself, I'd recommend you to go through following topics:
File I/O in C (because you most probably know C)
Standard streams in Unix
Pipes in Unix
ok sir
Sir I did those topics and rectified those errors as well. I also wrote a java code and gave its input through dart programme using process.
Dart code:
`import 'dart:io'; import 'dart:convert';
Future main()async { var p=await Process.start("java", ["Doingitfromdart.java"]); p.stdout.transform(utf8.decoder).forEach((element) {print(element);}); p.stdin.write("Karan "); p.stdin.write(19); p.stdin.write(" Gujarat India Earth!"); p.stdin.close(); } `
Java code: `import java.util.Scanner;
public class Doingitfromdart { public static void main(String[] Karan) { System.out.println("Programme started!");
//Biodata programme
// int age; String name,address,age; Scanner s=new Scanner(System.in); name=s.next(); age=s.next();
address=s.nextLine();
System.out.println(name+" is "+age+" years old and resident of "+address);
}
} `
Output: `C:/Dell/flutter/bin/cache/dart-sdk/bin/dart.exe --enable-asserts C:\Users\Dell\IdeaProjects\Processpractice\progprac2.dart Programme started!
Karan is 19 years old and resident of Gujarat India Earth!
Process finished with exit code 0`
It seems like a pipe mechanism since we are directly giving the input to java programme without any intermediate file. So ,now the commandline invocation of APISummarizer.jar gives us a very long output in the terminal which i should read through stdin of Process object and take it into a json file to have a clear picture of output. Right?
which i should read through stdin of Process object and take it into a json file to have a clear picture of output.
I don't get whether you understood the JSON part very well.
Currently we pass cli options. You know about command line options right? -optionname argument
format.
(If you don't, I encourage you to read about those command line option conventions.)
All this information has some structure.
For example, class path and source path are arrays of strings.
List of classes is also array of strings.
Some are simpler strings eg --backend=doclet
.
This structure (class SummarizerOptions) is already there which has all these fields. You just have to read it from JSON by creating a factory method which uses Jackson ObjectMapper
class. If you don't understand this part, read up on POJO types
and Jackson databind
library.
To create JSON, you need an equivalent type on dart side. You have to create a dart SummarizerOptions
class which mirrors the same java class. You can use json_serializable
library or write a manual function. Both are fine.
Keep this class in separate file in lib/src/summary/
This allows us to provide larger options without long command line, also it's a bit cleaner.
You still have to log the JSON in one-line. (Because logs have to be one line).
Also, dump the same JSON to .dart_tool/jnigen/summarizer_last_invocation.json
.
So that when debugging we can do
cat .dart_tool/jnigen/summarizer_last_invocation.json | java -jar .dart_tool/jnigen/ApiSummarizer.jar
.
Despite having this, you don't want to remove current command line mechanism, that's very useful for debugging.
So you may want to add a new option --read-params-from-stdin
, and in fromCommandLine
factory method, you first check for this argument and if present, return an object created from JSON. If you have an alternative idea here, you're welcome to discuss it, too.
Also you don't have to address us as "sir". It's not your college 🙂.
For writing the dart class that mirrors the Java class(SummarizerOptions) how will I get the values for those class variables to write in Json. I was looking through Config class but could find only source path,class path,and backend but there are more left
Good progress.
There is at least one more: summarizer.extraArgs
which can be passed to summarizer.
You should check the getSummary
function, and work backwards from Process call to understand what what is passed to summarizer. (I could check myself and tell, but it would be beneficial for you to learn these patterns).
As for supporting extra options, you have 2 choices:
You may want to change it to summarizer.extraConfig
which may be a Map
type we give in YAML. You will also have to change the corresponding parts where config is read from YAML.
Alternatively, you can take a simpler approach, by still supporting those extra flags, while taking main input from stdin.
So this is your choice as implementer. For me at the end code should be neat 🙂.
The Java part is getting it's cli options argument list from dart side if somehow that list is known i could get those remaining options But i couldn't find it
get summary function is returning a classes future and that is used in generating bindings should i study about bindings part or is there any other way
Read my comment again.
The CLI arguments list is passed through a process call.
You can look how each of these argument is constructed. That will tell you which parameters are passed. Rest of them are passed as extra args (needed only in rare cases).
How should I run my code for checking ?
I'm trying to extract the options and arguments from List
Maybe it was because I had made args a static late List
import 'dart:io';
import 'package:jnigen/src/logging/logging.dart'; import 'package:jnigen/src/summary/SummarizerOpts.dart'; import 'package:jnigen/src/tools/tools.dart'; import 'package:logging/logging.dart';
void main(List
} `
The Hi is visible but not the list.
Output: `C:/Dell/flutter/bin/cache/dart-sdk/bin/dart.exe --enable-asserts C:\Users\Dell\Desktop\jnigen\jnigen\bin\setup.dart Hi (jnigen) INFO: Building ApiSummarizer component. This might take some time. The build will be cached for subsequent runs
(jnigen) INFO: execute mvn --batch-mode --update-snapshots -f C:\Users\Dell\Desktop\jnigen\jnigen\java\pom.xml assembly:assembly
Process finished with exit code 0 `
And a Jar file is generated in jnigen/.dartool/jnigen/ApiSummarizer.jar
I tracked back the getSummary function to bin/jnigen.dart and did the same thing here.
it gave this error on running: `C:/Dell/flutter/bin/cache/dart-sdk/bin/dart.exe --enable-asserts C:\Users\Dell\Desktop\jnigen\jnigen\bin\jnigen.dart Fatal: Error parsing configuration: C output config must be provided!
Process finished with exit code 1 `
Why are you looking at setup.dart
? The code which spawns summarizer process is in summary.dart
.
Also didn't understand what your trying with print(Hi)
etc..
--
Side note: from the next time use GitHub markdown code blocks for pasting dart code.
```dart
// Dart code here
Actually I wanted to just run and check the changes I'm making
dart run jni:setup
builds ApiSummarizer in .dart_tool/jnigen/ApiSummarizer.jar
. (needs internet when running for the first time. That might be your first error).
You have run at least one of the examples right? If you don't have Android SDK setup, run jnigen in pdfbox example. You will see logs detailing what's happening.
If you didn't change options to JSON input yet, you can copy paste one of java -jar .dart_tool/jnigen/ApiSummarizer.jar .....
commands in logs and check JSON output is coming. (Output is already JSON, it will tell you which classes and methods are there in java file).
Otherwise you have to modify the command appropriately, to take new options or input you added. Once you add JSON input, you can prepare a JSON file and pipe it to command.
Once you add JSON input on dart side also, you can just run dart run jnigen --config jnigen.yaml
as usual.
When you're trying these, print the JSON etc.. you generate. But after you're done remove those prints.
which pdf box ?
!
jnigen/example/pdfbox_plugin
You understand what this project does, right? I assumed you have gone through README and examples.
Sir does this issue has any time bound. Actually I've got my mid semester exams this month so I'll try to do as much as I can for this month.
Take time. This doesn't have any milestones attached with it.
@Karan741187
It appears you posted a message in the thread and deleted it.
If that's the case, don't do it. Because people will receive email notifications about the issues anyway.
Regarding the issue - yeah it's perfectly fine to take time. You appear to be in 1st year from the bio that GitHub shows. You have ample time to learn things.
I will probably take up this issue if time permits. Else someone will. Not a problem.
Planning to rewrite APISummarizer in Dart. Closing this.
This is a summarizer command invocation on
in_app_java
sample after adding some gradle sources support.With an app which has more dependencies, we might cross OS-imposed limits of command length and it's not great for debugging either.
We should take this class paths etc information as structured JSON in summarizer, reading from
System.in
.