All Manuals > LispWorks User Guide and Reference Manual > 41 The LW-JI Package

NextPrevUpTopContentsIndex

generate-java-class-definitions

Function
Summary

Returns a list of forms which are definitions of Java callers that call the public methods (including constructors) of the supplied class, and accessors for public fields.

Package

lw-ji

Signature

generate-java-class-definitions java-class-name &key lisp-name package-name prefix name-constructor export-p create-defpackage lisp-class-p lisp-supers => list-of-definitions, lisp-name-symbol, package-name-string

Arguments

java-class-name

A string.

lisp-name

A symbol.

package-name

A string.

prefix

A string or nil.

name-constructor

A function designator.

export-p

A generalized boolean.

create-defpackage

A generalized boolean.

lisp-class-p

A generalized boolean.

lisp-supers

A list of symbols.

Values

list-of-definitions

A list.

lisp-name-symbol

A symbol.

package-name-string

A package name.

Description

The function generate-java-class-definitions returns a list of forms which are definitions of Java callers that call the public methods (including constructors) of the class specified by java-class-name, and accessors for public fields. These include inherited methods and fields.

generate-java-class-definitions is normally used indirectly by using import-java-class-definitions, but can also be used directly. write-java-class-definitions-to-file and write-java-class-definitions-to-stream do the same processing as generate-java-class-definitions, and then generate output based on the result.

java-class-name must name a Java class, and it must be the precise full name, for example "java.io.File", "android.view.View".

If lisp-name is supplied it must be a Lisp symbol. In this case it specifies the package to intern the names of definitions in, and if a CLOS class is defined, the name of this class. It is also automatically defined as a constant with a value the java-class-name. lisp-name can also be nil.

If lisp-name is not supplied, the system creates a Lisp symbol based on the java-class-name. Note that this is different from passing nil, because in the latter case lisp-name stays nil.

package-name is used only if lisp-name is supplied as nil, to specify the package where the names of the definitions are interned. It must be a string containing the package name (in the desired case). The package is created if it does not exist already. If lisp-name is nil and package-name is nil or not supplied, the current package is used.

prefix, if supplied, specifies a prefix to use for the names of the definitions. If prefix is not supplied or is nil, the name of the Java class without the package part is uppercased and used as the prefix (for example for "java.io.File" the prefix is "FILE"). The prefix is passed to the name-constructor to construct names for the Java callers.

If name-constructor is supplied, it must be a function taking two string arguments: the prefix and the name of the Java method or field that the Java caller is going to call or access (for constructors, the string "new" is passed as the method name). It must return a string which is then interned (without changing the case) in the package to create the symbol that is used as the name of the caller. The name-constructor defaults to a function (default-name-constructor) that concatenates the prefix as it is, a dot and uppercase of the method/field name. For example, for the method "exists" in the Java class "java.io.File", the default name constructor with the default prefix would generate "FILE.EXISTS".

export-p controls whether all the Java callers are exported from the package. If it is t all the Java callers are exported, otherwise they are not. The default of export-p is t.

create-defpackage controls what form to generate to do the package manipulation. With the default, generate-java-class-definitions generates a form that check that the package exists, otherwise creates it, and if export-p is t, a form that exports all the symbols. If create-defpackage is non-nil, generate-java-class-definitions generates a defpackage form instead. The default value of create-defpackage is nil.

Note: the reason the create-defpackage defaults to nil is that the defpackage form would contain only the symbols that were defined by the importing, which would be wrong if the package needs to export other symbols too, which is quite likely with the default settings (because other classes in the same Java package will default to use the same Lisp package). create-defpackage is useful when you want to create a package that exports only the definitions for a single Java class.

lisp-supers and lisp-class-p control whether a CLOS class is defined for the Java class. By default, no CLOS class is defined. See in Creating CLOS class.

The generation of the Java callers and accessors by generate-java-class-definitions is as follows:

  1. Based on the arguments as described above, it determines the what package, prefix and name-constructor to use, and whether it has a lisp-name and needs to define a CLOS class. It then finds the definition of the Java class.
  2. It uses Java methods to find the names of all the public methods, constructors and fields of the class (including inherited ordinary methods and fields).
  3. For each name, it calls the name-constructor with the prefix and the name to generate a symbol name which is then interned in the package to generate a symbol. It then generates a form where the operator is one of the macros define-java-caller, define-java-constructor, or define-field-accessor, as appropriate, using the symbol as the name.
  4. For example, with the defaults generating for "java.io.File", the constructor would be defined by

    (define-java-constructor FILE.NEW "java/io/File")

    The caller for the method "exists" would be defined by:

    (define-java-caller FILE.EXISTS "java/io/File" "exists")

    the accessor for for the field "separator" would be defined by:

    (define-field-accessor file.separator "java/io/File" "separator" t t)

    Note that generate-java-class-definitions uses '/' rather than '.' as separator between the components. The definer macros accept both '/' and '.' as separators. The actual generated forms may contain additional keywords. Currently methods and constructors have the signatures.

  5. generate-java-class-definitions also identifies pairs of methods where one has the name set<something> and the other has the name get<something> or is<something>, which are assumed to be setter and getter for the same field. It then generates a cl:setf definition to allow using cl:setf on the symbol corresponding to get<something> or is<something> name to call the set<something> method.
  6. For fields, generate-java-class-definitions also generates a symbol macro with a name that is the symbol name preceded and followed by the * character, and allows getting and the setting the field using this symbol.

The first return value of generate-java-class-definitions is a list of forms. The list contains the following forms in this order:

generate-java-class-definitions also returns the lisp-name (supplied or generated) as second return value, and the package name of the package that it used as third value.

Creating CLOS class

Note: see the discussion CLOS partial integration.

The arguments lisp-class-p, lisp-supers and lisp-name control whether the importing also defines a class. lisp-name and either lisp-supers or lisp-class-p must be non-nil to generate a Lisp class.

lisp-name, when non-nil, defines the name of the class. Note that by default lisp-name is not nil, because generate-java-class-definitions generates a symbol if lisp-name is not supplied.

If lisp-supers is supplied and non-nil (and lisp-name is non-nil) a class is created, using a plain defclass form, and the value lisp-class-p is ignored. lisp-supers must be a list of symbols naming classes, of which at least one is standard-java-object or a subclass of it. This list defines the superclasses of the class that is defined.

If lisp-class-p is non-nil and lisp-supers is nil (and lisp-name is non-nil) a class is created using ensure-lisp-classes-from-tree. If lisp-class-p is the keyword :complete, the force-p argument is passed is t, otherwise it is nil. See ensure-lisp-classes-from-tree for details.

generate-java-class-definitions returns three arguments: the list of definitions, the lisp-name and the package name.

Notes

generate-java-class-definitions require running Java Virtual Machine, and access to the class definition via the java.lang.reflect package functionality.

See also

write-java-class-definitions-to-stream
write-java-class-definitions-to-file
import-java-class-definitions
Importing classes


LispWorks User Guide and Reference Manual - 20 Sep 2017

NextPrevUpTopContentsIndex