UML drawing API for Java - java

I am looking for APIs that can draw UML Class diagrams and present them in a JPanel (or any other suitable UI entity) for a window application. It has to be embedded within the application, so I am not looking for some standalone tool that can generate UMLs based on java files or some plugin. I need actual jars that can be implemented for creating class diagrams so I can use them in a window application. I've looked into several but all of the sources that I am finding are either standalone programs or cannot be implemented within an application and need to take the user's focus away from the app. I am using NetBeans IDE, but I also have Eclipse installed.
SOLVED:
I used PlantUML API. I manually input a string in accordance with the PlantUML input language syntax and then used a simple and straightforward generateImage method to populate a byte array which I then converted into an image and saved it to my desktop. This fits what I wanted because it keeps the user focused on my application and mine alone. Alternatively, one can produce the buffered image on a window or something. The PlantUML API needs to be imported to the application package. This code creates an image in my desktop (don't forget to change the directory path) with a UML class image for the class, Person:
public class PaintUML {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, InterruptedException {
// TODO code application logic here
ByteArrayOutputStream bous = new ByteArrayOutputStream();
String source = "#startuml\n";
source += "class Person {\n";
source += "String name\n";
source += "int age\n";
source += "int money\n";
source += "String getName()\n";
source += "void setName(String name)\n";
source += "}\n";
source += "#enduml\n";
SourceStringReader reader = new SourceStringReader(source);
// Write the first image to "png"
String desc = reader.generateImage(bous);
// Return a null string if no generation
byte [] data = bous.toByteArray();
InputStream in = new ByteArrayInputStream(data);
BufferedImage convImg = ImageIO.read(in);
ImageIO.write(convImg, "png", new File("C:\\Users\\Aaron\\Desktop\\image.png"));
System.out.print(desc);
}
}

Have you seen PlantUML?
http://plantuml.sourceforge.net
It's open source so you might be able to pick some bits to suit.

Have a look at the Eclipse UML2 API and Eclipse Papyrus. They should provide the functionality what your are searching for. For drawing support in JPanels, you might need to do some extra work.
The Eclipse UML2 API provides a Java interface for UML2 meta model. Papyrus is a set of components allowing to build diagrams and graphical editors for UML models.

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;
}

How can I call a Java object/function from Oracle Forms 6i?

I am working on a legacy project that is using Oracle Forms 6i (yes, I know its old) to call C++ functions from a PLL library.
Now we need to use Java instead of C++, therefore we need to call Java (Object/Class/Method) from Oracle Forms.
I know its a challenging subject, but I would be really happy if someone could provide a simple example that does the following:
Invoking a method from the Java class, passing a int variable (within PL/SQL)
Printing the returned value in the Canvas that executed the Function.
A basic example, perhaps a Hello World would be ideal.
I know some PL/SQL, but I am not a Oracle Forms developer; please bear with me.
If this is not possible, could you point me to some other alternatives?
Well, after an intensive lookup through the internet I came across a very good resource (in Spanish though): Elias blog about Oracle Forms and Java
I use:
Oracle Forms 6i
JDK 1.6
With this I managed to create the hello world example:
Configure PATH environment variables:
C:\PATH_TO_JAVA\Java\jdk1.6.0\bin;
C:\PATH_TO_JAVA\Java\jdk1.6.0\jre\bin;
C:\PATH_TO_JAVA\Java\jdk1.6.0\jre\bin\client;
Ex: PATH_TO_JAVA = C:\Program Files
Add to CLASSPATH
FORMS_HOME\TOOLS\common60\JAVA\IMPORTER.JAR (In my case FORMS_HOME was C:\orant)
PATH_TO_YOUR_JAR\NAME_OF_JAR.jar
Create Java Program
Create with your IDE a simple java program, following is mine:
public class HiWorld{
private String hi="Hello World!";
public String getHi(){
return this.hi;
}
public String getMultiply(int a, int b){
return ""+a*b;
}
public static void main(String args[]){
HiWorld hm = new HiWorld();
System.out.println(hm.getHi());
System.out.println(hm.getMultiply(5,10));
}
}
Export it to Jar file (Path has to be the one you put in CLASSPATH environment variable.
Import the classes to Forms
Create a new project in Oracle Forms and also create a Canvas, in the canvas use a Text and a Button. The name of the button: TEXT_HI_WORLD.
Following click on the Menu: Program > Import Java Classes
If everything went Ok then there will be a new window that will show you the package where the Class is, you extend it until there is the HiWorld class. Import it.
In Program Unit now there will be two files:
HIWORLD (Specification)
HIWORLD (Body)
This are files generated automatically and needed to use the class.
Then go back to the canvas, right click on the Button and select the Thrigger WHEN-BUTTON-PRESSED, the programming of this will be:
DECLARE
v_wb ORA_JAVA.JOBJECT;
v_hi VARCHAR2(20);
BEGIN
v_wb := hiworld.new();
v_hi:= hiworld.getHi(v_wb);
:TEXT_HI_WORLD := v_hi
END;
Now execute the program and click on the button! :)
Hope this helps Java programmers with no much of knowledge on Forms to integrate with legacy systems! :D
I've done this before, and with a simple class this should work, but when you try to develop something more complicated, I recommend extend from the VBean class, you can find the library within oracle's forms installation folders (frmall.jar).
// el programa corregido.
public class HolaMundo {
private String hi= "Hey World!!!";
public String GetHi(){
return this.hi;
}
public static void main(String args[]){
HolaMundo hm = new HolaMundo();
System.out.println(hm.GetHi());
}
}

is it possible to create a java applet, during execution of another java application

I have been developing a Java application which executes a long series of queries and calculations, and presents its results as a series of HTML pages. For visualizing graphs I have been playing around with JUNG library for a while, and it appears as the real strength of the library is the support for user interaction, which is of course unavailable when the graph is saved as a static image (PNG in my case).
I was wondering if it would be:
a) possible
b) feasible
c) sensible
... to create an applet, during execution of the main application, which then can be insert to the HTML reports and can be used interactively after the application has finished execution and the user goes through the report pages.
If this is not possible due to technical reasons; do you have any alternative recommendations/ suggestions as to how I can achieve something like this?
Thanks,
EDIT: Just to clarify the concept, the "main" application is a link in a chain of events, and thus has so separate GUI. The idea with the applet is NOT to mimic or transport all the stuff from the main app to a HTML page, but to make it possible to use interactive tools that come with JUNG library, when the user is reviewing the graphical results AFTER the execution of the main software has finished.
Let me know if the concept is still rather unclear and I'll give a second attempt to explain things in further detail.
UPDATE: Following the advices I got, thnx to #boffinBrain & #AndrewThompson, I wrote my applet, and placed in a package in my project along with other visualization related classes. The hierarchy is as follows:
my.domain.project
my.domain.project.tests
my.domain.project.visualization
Now the HTML reports are created at an arbitrary location on the local drive, this is a feature as the user gives an output folder prior to running the "main" application. In my ReportGenerator class (which generates these HTML files) I have the following bit of code:
File bin = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toString());
String codebase = bin.getParent();
System.out.println(codebase);
String archive = "lib/collections-generic-4.01/collections-generic-4.01.jar";
String applet_name = "bin/my.domain.project.visualization.HierarchyGraphApplet.class";
codebase printout shows: file:/home/username/workspace/project which is correct what I'd expected. Under the project folder there's bin/ and lib/, and inside bin there is the right hierarchy of folders all the way down to my applet class which also exists.
Now why did I write all this down; well because when I try to run my applet on the reports I get:
java.lang.NoClassDefFoundError: bin/my/domain/project/visualization/HierarchyGraphApplet (wrong name: my/domain/project/visualization/HierarchyGraphApplet)
I have read similar questions like: this or this but it seems like the problem is somewhere else. I double checked the spelling etc...
Is there something simple I am missing, or is there a more complicated problem at hand?
Maybe this example will give you some ideas to pursue. It creates data files used as 'reports' for consumption by the applet(s).
Because the applet gains the data via an input file whose title is specified in an applet param. The content of the data file is only limited by the requirements of the report, your skill to create it & parse it, ..and available disk space. ;)
Compile & run the main(String[]) to (hopefully) see 2 web pages open in tabs of your browser.
import java.awt.Desktop;
import javax.swing.*;
import java.net.*;
import java.io.*;
/** Simplistic example, not intended to show good I/O practices
or Exception handling for the sake of brevity. */
public class Reporter extends JApplet {
public void init() {
String input = getParameter("input");
JEditorPane report = new JEditorPane();
report.setText("Problem loading input file");
add(report);
URL url;
try {
url = new URL(getDocumentBase(), input);
report.setPage(url);
} catch(Exception e) {
e.printStackTrace();
}
}
/** The main represents our report generator. It is part
of the applet class only in order to create an SSCCE. Good
design would imply that it might be in a class ReportGenerator,
while the applet is in class ReportViewer. */
public static void main(String[] args) throws Exception {
File f;
String title = "1";
String data = "apples";
createInput(title, data);
f = createHTML(title);
Desktop.getDesktop().browse(f.toURI());
title = "2";
data = "oranges";
createInput(title, data);
f = createHTML(title);
Desktop.getDesktop().browse(f.toURI());
System.out.println( "End of report generation.." );
}
public static void createInput(String title, String data) throws Exception {
File f = new File("data" + title + ".txt");
PrintWriter pw = new PrintWriter(f);
pw.println(data);
pw.flush();
pw.close();
}
public static File createHTML(String title) throws Exception {
File f = new File("Data" + title + ".html");
PrintWriter pw = new PrintWriter(f);
pw.println("<html>");
pw.println("<title>");
pw.println("Data " + title);
pw.println("<title>");
pw.println("<body>");
pw.println("<h1>");
pw.println("Data " + title);
pw.println("</h1>");
pw.println("<applet ");
pw.println("code='Reporter'");
pw.println("width='400'");
pw.println("height='400'");
pw.println(">");
pw.println("<param name='input' value='data" + title + ".txt'>");
pw.println("</applet>");
pw.println("</body>");
pw.println("</html>");
pw.flush();
pw.close();
return f;
}
}
In relation to further questions:
..does the given code assume that the html reports and the applet are located in the same folder?
Not necessarily. The input parameter might specify ../other/data3.txt for the other directory at the same level as the one contained by the HTML, or /reports/data3.txt for a reports directory at the root of the site.
..As you have also noted, in a real-life example the code for the applet would most likely be in its own class, would that pose any complications as to how it would be incorporated into the html files (which are generated in a separate class, named ReportGenerator)?
It would require only slight changes to point to the applet.jar as opposed to the application.jar. Use a codebase to separate the HTML from the directory of the applet.jar (though archives can also be accessed via relative or absolute URLs).
It's definitely feasible to create an applet to display the data, but you don't want to dynamically generate a new one each time. You want to create a separate, stand-alone applet which can generate your graphs/reports from a set of input data in text format, and then when you create the HTML page, supply the report data using an applet parameter (using the PARAM tag).

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.

lazily compile JasperReports .jrxml to .jasper

I use Jasper reports with the JasperReportsMultiFormatView class provided by the Spring framework. This class takes care of compiling the source .jrxml files to their compiled .jasper format when the Spring application context is created.
However, this compilation process is really slowing down the application startup time. Is it possible for the reports to be lazily compiled instead of compiled at startup time, i.e. a report is only compiled the first time it is requested?
If this is not possible, alternative suggestions for how I can reduce/eliminate the report compilation time would be welcome. Of course, I could mandate that the compiled reports must be checked into SVN along with the .jrxml files, but it's only a matter of time, before someone (most likely me) forgets.
Cheers,
Don
I, like you, started out with the Spring helper classes for Jasper Reports but quickly abandoned them as being too coarse-grained and inflexible, which is unusual for Spring. Its like they were added as an afterthought.
The big problem I had with them was that once they were compiled, it required an appserver bounce to put in new versions. In my case, I was after a solution whereby I could change them on disk and they'd recompile, much like how JSPs normally work (if you don't turn this feature off, which many production sites would).
Alternatively, I wanted to be able to store the jrxml files in a database or run the reports remotely (eg through the JasperServer web services interface). The Spring classes just made it all but impossible to implement such features.
So my suggestion to you is: roll your own. There are a couple of gotchas along the way though, which I'll share with you to minimize the pain. Some of these things aren't obvious from the documentation.
The first thing you'll need is a jasper reports compiler. This is responsible for compiling a jrxml file into a JasperDesign object. There are several implemenations of this but the one you want is the JRJdtCompiler. You can instantiate and inject this in a Spring application context. Avoid others like the beanshell compiler since running the report as a large beanshell script is not particularly fast or efficient (I found this out the hard way before I knew any better).
You will need to include the jar files for the JRJdtCompiler. I think the full Jasper Reports dist includes this jar. Its an eclipse product.
You can store the JasperDesign anywhere you like (HttpSession, servlet context or whatever). The fillReport() method is the primary one you're interested in. It creates a JasperPrint object, which is an instance of a run report. Parameters are just passed in as a Map.
Now to create a versino in HTML, PDF, etc, you need to export it. You use classes like the JRHtmlExporter and JRPdfExporter to do this. They require certain parameters. The tricky one is the HTML exporter because HTML obviously doesn't include the images. Jasper includes an ImageServlet class that fetches these from the session (where the JRHtmlExporter has put them) but you have to get the config of both the HTML exporter and image servlet just right and its hard to tell where you're going wrong.
I don't remember the specifics of it but theres an example of all this in the Jasper Reports Definitive Guide, which I'd highly recommend you get if you're spending anytime at all with this product. Its fairly cheap at US$50. You could get the annual subscription too but in the 18+ months I've seen it I haven't seen a single change. Just buy the new version when it comes out if you need it (which you probably won't).
Hope this helps.
The report is compiled the first time its run, put a break point in AbstractJasperReportsView protected final JasperReport loadReport(Resource resource) method to confirm this.
However the above post is correct that you'll need to extend the JasperReportsMultiFormatView if you want to provide any specific compilation process.
A great example of dynamic compilation is here: http://javanetspeed.blogspot.com/2013/01/jasper-ireport-with-java-spring-and.html
import net.sf.jasperreports.engine.JasperReport;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView;
public class DynamicJasperReportsMultiFormatView extends JasperReportsMultiFormatView {
private static final Logger LOG = Logger.getLogger(DynamicJasperReportsMultiFormatView.class);
/**
* The JasperReport that is used to render the view.
*/
private JasperReport jasperReport;
/**
* The last modified time of the jrxml resource file, used to force compilation.
*/
private long jrxmlTimestamp;
#Override
protected void onInit() {
jasperReport = super.getReport();
try {
String url = getUrl();
if (url != null) {
jrxmlTimestamp = getApplicationContext().getResource(url).getFile().lastModified();
}
} catch (Exception e) {
e = null;
}
}
#Override
protected JasperReport getReport() {
if (this.isDirty()) {
LOG.info("Forcing recompilation of jasper report as the jrxml has changed");
this.jasperReport = this.loadReport();
}
return this.jasperReport;
}
/**
* Determines if the jrxml file is dirty by checking its timestamp.
*
* #return true to force recompilation because the report xml has changed, false otherwise
*/
private boolean isDirty() {
long curTimestamp = 0L;
try {
String url = getUrl();
if (url != null) {
curTimestamp = getApplicationContext().getResource(url).getFile().lastModified();
if (curTimestamp > jrxmlTimestamp) {
jrxmlTimestamp = curTimestamp;
return true;
}
}
} catch (Exception e) {
e = null;
}
return false;
}
}

Categories

Resources