/**
* 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())