/** * Class that represents a Java Package. * * @author Martin Bravenboer <martin@cs.uu.nl> */ module dryad/model/package imports dryad/model/repository dryad/util/option strategies /** * Creates a new package. If not parent package is specified, then * the new package is a top level package. * * @param Optional parent (Some(Package Object)) * @param Name of the package (String) * @type _ -> Package Object */ new-package(|opt-parentpkg, simple-name) = <classes_get-class> JavaPackage() ; classes_new-instance ; classes_set-instance-field(|"simple-name", simple-name) ; classes_set-instance-field(|"package-table", <new-hashtable>) ; if !opt-parentpkg => Some(pkg) then classes_set-instance-field(|"parent-package", pkg) end /** * Succeeds if this is the root package. * * @type Package Object -> Package Object */ is-root-package = where(not(get-parent-package)) /** * Returns the parent package. * Fails if this is the root (default) package. * * @type Package Object -> Package Object */ get-parent-package = instanceof-JavaPackage; classes_get-instance-field(|"parent-package") /** * Names */ strategies /** * Returns the simple name of this package. * i.e. package org.foo.bar will return "bar". * * @type Package Object -> String */ get-simple-name = instanceof-JavaPackage; classes_get-instance-field(|"simple-name") /** * Returns the canonical name of this package. * * @type Package Object -> TypeName */ get-canonical-name = instanceof-JavaPackage; ?this; let do = !PackageName(<private-get-fully-qualified-name(|[])>) in classes_get-instance-field(do |"fully-qualified-name") end /** * Returns the full qualified name of this package. * * @type Package Object -> TypeName */ get-fully-qualified-name = instanceof-JavaPackage; get-canonical-name /** * Private helper. Don't invoke directly. * * @type Package Object -> List(Id) */ private-get-fully-qualified-name(|acc) = instanceof-JavaPackage; ?this; if get-parent-package => pkg then <private-get-fully-qualified-name(|[Id(<get-simple-name> this) | acc])> pkg else !acc end strategies /** * Returns all subpackages. * * @type Package Object -> List(Package Object) */ get-subpackages = instanceof-JavaPackage; classes_get-instance-field(|"package-table") ; hashtable-values /** * Returns the subpackage of the specified name. * This strategy fails if there is no subpackage with this name. * * @param Name of the package (String) * @type Package Object -> Package Object */ get-subpackage(|name) = instanceof-JavaPackage; classes_get-instance-field(|"package-table") ; hashtable-get(|name) /** * Creates a new subpackage in the current package. * Returns the package object of the new subpackage. * * @param String * @type Package Object -> Package Object */ add-subpackage(|name) = instanceof-JavaPackage; ?this; where(new-package(|Some(this), name) => pkg) ; classes_get-instance-field(|"package-table") ; hashtable-put(|name, pkg) ; !pkg /** * Ensures that a subpackage exists in the current package. * * @param String * @type Package Object -> Package Object */ get-or-add-subpackage(|name) = get-subpackage(|name) <+ add-subpackage(|name) /** * Returns the direct or indirect subpackage of the given name. * The subpackage can be multiple levels deep. * * For example, in current package 'org' invoking this * strategy with names ["foo", "bar"], will return the * package 'org.foo.bar' (if this package exists). * * @param List(String) * @type Package Object -> Package Object */ get-subsubpackage(|names) = foldl(get-subpackage | names) /** * Ensures that a subpackage exists in the current package. * The subpackage can be multiple levels deep. * * For example, in current package 'org' invoking this * strategy with names ["foo", "bar"], will create a * subpackage 'org.foo.bar'. * * @param List(String) * @type Package Object -> Package Object */ get-or-add-subsubpackage(|names) = instanceof-JavaPackage; foldl(get-or-add-subpackage | names) /** * Succeeds if this package has a subpackage 'name' * * @param String * @type Package Object -> Package Object */ has-subpackage(|name) = where(get-subpackage(|name)) /** * Alias of has-subpackage. */ is-subpackage(|name) = has-subpackage(|name) /** * @type Package Object -> Package Object */ is-subsubpackage(|names) = where(get-subsubpackage(|names)) /** * @todo Set the package object of the class? * @type Package Object -> Package Object */ add-toplevel-class(|class) = instanceof-JavaPackage; ?this ; where(<get-simple-name> class => name) ; where( get-toplevel-classtable ; hashtable-put(|name, class) ) /** * Succeeds if this package has a toplevel class of the specified name. * * @param Name of the class (String) * @type Package Object -> Package Object */ has-toplevel-class(|name) = where(get-toplevel-class(|name)) /** * @type Package Object -> Class Object */ get-toplevel-class(|name) = instanceof-JavaPackage; get-toplevel-classtable ; hashtable-get(|name) /** * @type Package Object -> List(Class Object) */ get-toplevel-classes = instanceof-JavaPackage; get-toplevel-classtable => classtbl ; hashtable-keys ; map( \ name -> <hashtable-get(|name)> classtbl \ ) strategies /** * @type Package Object -> Hashtable(String, Class Object) */ get-toplevel-classtable = instanceof-JavaPackage; classes_get-instance-field(init-toplevel-bytecode-classes | "classtable") /** * @todo Check if the table is already there. If so, then we have to add * the classes to the actual table. */ set-toplevel-bytecode-classes(|data) = instanceof-JavaPackage; ?this; where( if classes_get-instance-field(|"lazy-classtable") => data1 then <union> (data, data1) else !data end ; ?realdata ; <classes_set-instance-field(|"lazy-classtable", realdata)> this ) init-toplevel-bytecode-classes = instanceof-JavaPackage; ?pkg ; new-hashtable => toplevel ; if <classes_get-instance-field(|"lazy-classtable")> pkg => classes then !classes ; let create-class = {class, simplename, location, memberclasses: ?Class(simplename, location, memberclasses) ; new-bytecode-class(|simplename) => class ; set-location(|location) ; set-package(|pkg) ; <map({nestedclass: create-class => nestedclass ; <add-declared-member-type(|nestedclass)> class ; <set-declaring-class(|class)> nestedclass })> memberclasses ; !class } in map({simplename, class: create-class => class ; <get-simple-name> class => simplename ; <hashtable-put(|simplename, class)> toplevel }) end end ; !toplevel /** * Stratego Class support for packages */ signature constructors /** * Identifier for the class Package. */ JavaPackage : ClassName strategies instanceof-JavaPackage = classes_instanceof(|JavaPackage())