Hi,
I did a quick hack to populate the information for a class from a
java file. It almost certainly leaks memory as i haven't done C in
years but it does the trick for me. I've attached a patch for my
changes.
Hope its use for someone.
Fin.
--
Common subdirectories: fii/dia/objects/UML/CVS and dia/objects/UML/CVS
diff -NU3 fii/dia/objects/UML/class.h dia/objects/UML/class.h
--- fii/dia/objects/UML/class.h Tue Jan 2 21:09:48 2001
+++ dia/objects/UML/class.h Tue Feb 27 22:41:17 2001
@@ -27,6 +27,7 @@
typedef struct _UMLClass UMLClass;
typedef struct _UMLClassDialog UMLClassDialog;
+typedef struct _UMLClassState UMLClassState;
struct _UMLClass {
Element element;
@@ -94,6 +95,7 @@
GtkToggleButton *attr_supp;
GtkToggleButton *op_vis;
GtkToggleButton *op_supp;
+ GtkFileSelection *file_sel;
DiaColorSelector *fg_color;
DiaColorSelector *bg_color;
@@ -134,6 +136,26 @@
GtkToggleButton *templ_template;
GtkEntry *templ_name;
GtkEntry *templ_type;
+};
+
+struct _UMLClassState {
+ char *name;
+ char *stereotype;
+ int abstract;
+ int suppress_attributes;
+ int suppress_operations;
+ int visible_attributes;
+ int visible_operations;
+
+ /* Attributes: */
+ GList *attributes;
+
+ /* Operators: */
+ GList *operations;
+
+ /* Template: */
+ int template;
+ GList *formal_params;
};
extern GtkWidget *umlclass_get_properties(UMLClass *umlclass);
diff -NU3 fii/dia/objects/UML/class_dialog.c dia/objects/UML/class_dialog.c
--- fii/dia/objects/UML/class_dialog.c Thu Mar 1 14:02:17 2001
+++ dia/objects/UML/class_dialog.c Wed Feb 28 16:20:47 2001
@@ -24,13 +24,17 @@
#include <gtk/gtk.h>
#include <math.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <glib.h>
#include "config.h"
#include "object.h"
#include "objchange.h"
#include "intl.h"
#include "class.h"
-
+#include "parse.h"
typedef struct _Disconnect {
ConnectionPoint *cp;
@@ -38,29 +42,6 @@
Handle *other_handle;
} Disconnect;
-typedef struct _UMLClassState UMLClassState;
-
-struct _UMLClassState {
- char *name;
- char *stereotype;
- int abstract;
- int suppress_attributes;
- int suppress_operations;
- int visible_attributes;
- int visible_operations;
-
- /* Attributes: */
- GList *attributes;
-
- /* Operators: */
- GList *operations;
-
- /* Template: */
- int template;
- GList *formal_params;
-};
-
-
typedef struct _UMLClassChange UMLClassChange;
struct _UMLClassChange {
@@ -81,6 +62,8 @@
static ObjectChange *new_umlclass_change(UMLClass *obj, UMLClassState *saved_state,
GList *added, GList *deleted,
GList *disconnected);
+static void attribute_list_item_destroy_callback(GtkWidget *list_item, gpointer data);
+static void operations_list_item_destroy_callback(GtkWidget *list_item, gpointer
+data);
/**** Utility functions ******/
static void
@@ -162,6 +145,123 @@
dia_color_selector_set_color(prop_dialog->bg_color, ¨class->color_background);
}
+static void
+state_fill_in_dialog(UMLClassState *state, UMLClassDialog *prop_dialog)
+{
+ if (state->name != NULL)
+ gtk_entry_set_text(prop_dialog->classname, state->name);
+ else
+ gtk_entry_set_text(prop_dialog->classname, "");
+
+ if (state->stereotype != NULL)
+ gtk_entry_set_text(prop_dialog->stereotype, state->stereotype);
+ else
+ gtk_entry_set_text(prop_dialog->stereotype, "");
+
+ gtk_toggle_button_set_active(prop_dialog->abstract_class, state->abstract);
+ gtk_toggle_button_set_active(prop_dialog->attr_vis, state->visible_attributes);
+ gtk_toggle_button_set_active(prop_dialog->op_vis, state->visible_operations);
+ gtk_toggle_button_set_active(prop_dialog->attr_supp, state->suppress_attributes);
+ gtk_toggle_button_set_active(prop_dialog->op_supp, state->suppress_operations);
+}
+
+static void
+file_dialog_show(GtkButton *butt, GtkWidget *file_dialog)
+{
+ gtk_widget_show(file_dialog);
+}
+
+static void
+file_dialog_cancel(GtkButton *butt, GtkWidget *file_dialog)
+{
+ gtk_widget_hide(file_dialog);
+}
+
+static void
+op_add(UMLOperation *op,UMLClass *umlclass)
+{
+ GList *list;
+ UMLClassDialog *prop_dialog;
+ GtkWidget *list_item;
+ char *str;
+
+ prop_dialog = umlclass->properties_dialog;
+
+ str = uml_get_operation_string(op);
+ list_item = gtk_list_item_new_with_label(str);
+ gtk_widget_show(list_item);
+ g_free(str);
+
+ gtk_object_set_user_data(GTK_OBJECT(list_item), op);
+ gtk_signal_connect (GTK_OBJECT (list_item), "destroy",
+ GTK_SIGNAL_FUNC (operations_list_item_destroy_callback),
+ NULL);
+
+ list = g_list_append(NULL, list_item);
+ gtk_list_append_items(prop_dialog->operations_list, list);
+}
+
+static void
+at_add(UMLAttribute *attr,UMLClass *umlclass)
+{
+ GList *list;
+ UMLClassDialog *prop_dialog;
+ GtkWidget *list_item;
+ char *str;
+
+ prop_dialog = umlclass->properties_dialog;
+
+ str = uml_get_attribute_string(attr);
+ list_item = gtk_list_item_new_with_label(str);
+
+ gtk_widget_show(list_item);
+ g_free(str);
+
+ gtk_object_set_user_data(GTK_OBJECT(list_item), attr);
+ gtk_signal_connect (GTK_OBJECT (list_item), "destroy",
+ GTK_SIGNAL_FUNC (attribute_list_item_destroy_callback),
+ NULL);
+
+ list = g_list_append(NULL, list_item);
+ gtk_list_append_items(prop_dialog->attributes_list, list);
+}
+
+static void
+file_dialog_ok(GtkButton *butt, UMLClass *umlclass)
+{
+ UMLClassState state;
+ gchar *filename;
+ int file;
+
+ filename = gtk_file_selection_get_filename(umlclass->properties_dialog->file_sel);
+ file = open(filename, O_RDONLY, NULL);
+ if(file == -1){
+ g_print("Could not open %s\n",filename);
+ return;
+ }
+
+ gtk_widget_hide(GTK_WIDGET(umlclass->properties_dialog->file_sel));
+
+ state.name=NULL;
+ state.stereotype=NULL;
+ state.abstract=0;
+ state.suppress_attributes=0;
+ state.suppress_operations=0;
+ state.visible_attributes=1;
+ state.visible_operations=1;
+ state.attributes=NULL;
+ state.operations=NULL;
+ state.template=0;
+ state.formal_params=NULL;
+ if(scan_file(filename, file, &state)){
+ state_fill_in_dialog(&state,umlclass->properties_dialog);
+ g_list_foreach(state.operations, &op_add, (gpointer)umlclass);
+ g_list_foreach(state.attributes, &at_add, (gpointer)umlclass);
+ }
+ /* tidy up memory */
+}
+
+
static void
class_create_page(GtkNotebook *notebook, UMLClass *umlclass)
{
@@ -174,6 +274,7 @@
GtkWidget *checkbox;
GtkWidget *color_background;
GtkWidget *color_foreground;
+ GtkWidget *file_button;
prop_dialog = umlclass->properties_dialog;
@@ -255,6 +356,21 @@
dia_color_selector_set_color((DiaColorSelector *)color_background,
¨class->color_background);
prop_dialog->bg_color = (DiaColorSelector *)color_background;
gtk_box_pack_end( GTK_BOX(hbox), color_background, TRUE, TRUE,0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 5);
+ label = gtk_label_new(_("Reverse engineer class"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+ gtk_box_pack_start( GTK_BOX(hbox), label, TRUE, TRUE, 0);
+ file_button = gtk_button_new_with_label(_("Select File"));
+ prop_dialog->file_sel = GTK_FILE_SELECTION(gtk_file_selection_new(_("Reverse
+Engineer Class")));
+ gtk_signal_connect ( GTK_OBJECT (prop_dialog->file_sel->cancel_button), "clicked",
+ &file_dialog_cancel, prop_dialog->file_sel);
+ gtk_signal_connect ( GTK_OBJECT (prop_dialog->file_sel->ok_button), "clicked",
+ &file_dialog_ok, umlclass);
+ gtk_signal_connect ( GTK_OBJECT (file_button), "clicked",
+ &file_dialog_show, prop_dialog->file_sel);
+ gtk_box_pack_end( GTK_BOX(hbox), file_button, TRUE, TRUE,0);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
gtk_widget_show_all (vbox);
diff -NU3 fii/dia/objects/UML/parse.c dia/objects/UML/parse.c
--- fii/dia/objects/UML/parse.c Thu Jan 1 01:00:00 1970
+++ dia/objects/UML/parse.c Wed Feb 28 15:53:07 2001
@@ -0,0 +1,229 @@
+#include <gtk/gtk.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <glib.h>
+
+#include "intl.h"
+/* #include "class.h"*/
+#include "parse.h"
+
+static int nsymbols = 10;
+static char* symbol[] = {"public","private","protected","abstract","class",
+ "interface","static","extends","implements","throws"};
+
+static void
+add_operation(UMLClassState *state, UMLVisibility visibility, gchar *type,
+ gchar *name, gboolean is_static, gboolean abstract)
+{
+ UMLOperation *op=uml_operation_new();
+
+ g_print("Adding operation: %d %s %s\n", visibility, type, name);
+ op->name = name;
+ op->type = type;
+ op->visibility=visibility;
+ if(is_static)
+ op->class_scope = 1;
+ if(abstract)
+ op->abstract = 1;
+
+ state->operations = g_list_append(state->operations, op);
+}
+
+static void
+add_attribute(UMLClassState *state, UMLVisibility visibility, gchar *type,
+ gchar *name, gboolean is_static)
+{
+ UMLAttribute *at=uml_attribute_new();
+
+ g_print("Adding parameter: %d %s %s\n", visibility, type, name);
+ at->name = name;
+ at->type = type;
+ at->visibility=visibility;
+ if(is_static)
+ at->class_scope = 1;
+
+ state->attributes = g_list_append(state->attributes, at);
+}
+
+static GScanner*
+get_scanner(int file)
+{
+ GScanner *scanner;
+ int i;
+
+ scanner = g_scanner_new(NULL);
+ scanner->config->cset_identifier_nth = g_strjoin(NULL,
+scanner->config->cset_identifier_nth,
+ _("."), NULL);
+
+ for(i=0;i<nsymbols; i++)
+ g_scanner_scope_add_symbol(scanner, 0, _(symbol[i]), _(symbol[i]));
+
+ g_scanner_input_file(scanner, file);
+
+ return scanner;
+}
+
+
+/**
+ * Simplified java grammar
+ *
+ * FILE := [ HEADER ]* ( CLASS | INTERFACE )
+ * HEADER := id* ;
+ * CLASS := [abstract] [(public | protected | private)] class id [extends id]
+[implements id [,id]*] { CLASSBODY }
+ * INTERFACE := [public] interface id [extends id] { INTERFACEBODY }
+ * CLASSBODY := [(VAR | METHOD | CONSTRUCTOR | INITIALISER)] CLASSBODY
+ * VAR := [(public | protected | private)] id id;
+ * METHOD := [abstract] [synchronized] [static] [(public | protected | private)] id
+id ( [ PARAMS ] ) [ throws id [,id]* ] { don't care }
+ * CONSTRUCTOR := [(public | protected | private)] id ( [ PARAMS ] ) [ throws id
+[,id]* ] { don't care }
+ * INITIALISER := [static] { don't care }
+ * INTERFACEBODY := [synchronized] [(public | protected | private)] id id ( [ PARAMS
+] ) [ throws id [,id]* ] ; INTERFACEBODY
+ *
+ */
+static int
+parse_java_file(int file, UMLClassState *state)
+{
+ GTokenType tokentype;
+ gchar *name=NULL;
+ int depth=0,depth2=0;
+ gboolean expectingClass=FALSE;
+ gboolean expectingType=FALSE;
+ gboolean expectingOperation=FALSE;
+ gboolean expectingParams=FALSE;
+ gboolean interface=FALSE;
+ gboolean abstract=FALSE;
+ gboolean is_static=FALSE;
+
+ UMLVisibility visibility=UML_IMPLEMENTATION;
+ gchar *type=NULL;
+
+ GScanner *scanner=get_scanner(file);
+
+ while((tokentype = g_scanner_get_next_token(scanner))!= G_TOKEN_EOF){
+ GTokenValue gtv = g_scanner_cur_value(scanner);
+ switch(tokentype){
+ case G_TOKEN_LEFT_CURLY:
+ depth++;
+ if(depth < 2){
+ expectingType=TRUE;
+ }
+ if(expectingParams){
+ if(type != NULL && name != NULL)
+ add_operation(state, visibility, type, name, is_static, abstract);
+ }
+
+ type=NULL;
+ name=NULL;
+ expectingOperation=FALSE;
+ expectingParams=FALSE;
+ abstract=FALSE;
+ is_static=FALSE;
+ visibility=UML_IMPLEMENTATION;
+ break;
+ case G_TOKEN_RIGHT_CURLY:
+ depth--;
+ break;
+ case G_TOKEN_LEFT_PAREN:
+ depth2++;
+ break;
+ case G_TOKEN_RIGHT_PAREN:
+ depth2--;
+ break;
+ case ';':
+ if(depth == 1){
+ expectingType=TRUE;
+ expectingOperation=FALSE;
+ expectingParams=FALSE;
+
+ if(type != NULL && name != NULL){
+ if(interface)
+ add_operation(state, visibility, type, name, is_static, abstract);
+ else
+ add_attribute(state, visibility, type, name, is_static);
+ }
+ } else if(depth == 0){
+ expectingType=FALSE;
+ expectingOperation=FALSE;
+ expectingParams=FALSE;
+ }
+
+ type=NULL;
+ name=NULL;
+ abstract=FALSE;
+ is_static=FALSE;
+ visibility=UML_IMPLEMENTATION;
+
+ break;
+ case G_TOKEN_IDENTIFIER:
+ if(depth < 2 && depth2 < 1)
+ {
+ if(expectingClass){
+ state->name = strdup(gtv.v_identifier);
+ expectingClass=FALSE;
+ }
+ if(expectingType){
+ type = g_strdup(gtv.v_identifier);
+
+ expectingOperation=TRUE;
+ expectingType=FALSE;
+ } else if(expectingOperation){
+ name = g_strdup(gtv.v_identifier);
+
+ expectingOperation=FALSE;
+ expectingType=FALSE;
+ expectingParams=TRUE;
+ }
+ }
+ break;
+ case G_TOKEN_SYMBOL:
+ if(depth < 1){
+ if(strcmp(gtv.v_symbol, _("abstract"))==0){
+ state->abstract=1;
+ }
+ if(strcmp(gtv.v_symbol, _("interface"))==0){
+ state->stereotype = strdup("interface");
+ state->visible_attributes=0;
+ expectingClass=TRUE;
+ interface=TRUE;
+ visibility = UML_PUBLIC;
+ }
+ if(strcmp(gtv.v_symbol, _("class"))==0){
+ state->stereotype = strdup("");
+ expectingClass=TRUE;
+ }
+ } else if(depth < 2) {
+ if(strcmp(gtv.v_symbol, _("public"))==0) {
+ expectingType = TRUE;
+ visibility = UML_PUBLIC;
+ }
+ if(strcmp(gtv.v_symbol, _("protected"))==0) {
+ expectingType = TRUE;
+ visibility = UML_PROTECTED;
+ }
+ if(strcmp(gtv.v_symbol, _("private"))==0) {
+ expectingType = TRUE;
+ visibility = UML_PRIVATE;
+ }
+ if(strcmp(gtv.v_symbol, _("static"))==0) {
+ is_static = TRUE;
+ }
+ if(strcmp(gtv.v_symbol, _("abstract"))==0) {
+ abstract = TRUE;
+ }
+ }
+ default:
+ }
+ }
+ g_scanner_destroy(scanner);
+ g_print("Finished scanning file\n");
+ return 1;
+}
+
+extern int scan_file(gchar* filename, int file, UMLClassState *state)
+{
+ if(strstr(filename, ".java") != NULL)
+ return parse_java_file(file, state);
+
+ return 0;
+}
diff -NU3 fii/dia/objects/UML/parse.h dia/objects/UML/parse.h
--- fii/dia/objects/UML/parse.h Thu Jan 1 01:00:00 1970
+++ dia/objects/UML/parse.h Wed Feb 28 15:53:19 2001
@@ -0,0 +1,26 @@
+/* Dia -- an diagram creation/manipulation program
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PARSE_H
+#define PARSE_H
+
+#include "class.h"
+
+extern int scan_file(gchar *filename, int file, UMLClassState *state);
+
+#endif /* PARSE_H */
+
Common subdirectories: fii/dia/objects/UML/pixmaps and dia/objects/UML/pixmaps