Skip to content

Instantly share code, notes, and snippets.

@paulp
Created January 27, 2012 16:27
Show Gist options
  • Save paulp/1689615 to your computer and use it in GitHub Desktop.
Save paulp/1689615 to your computer and use it in GitHub Desktop.
// a.scala
// Fri Jan 27 08:21:56 PST 2012
class ModuleID(val organization: String, val name: String, val revision: String)
trait ProviderCreation {
def fromUrls(urls: Seq[URL]): MultiProvider
def fromUrl(url: URL): UrlProvider
def fromPath(path: PathType): SinglePathProvider
def fromClassPath(classPath: String): ClassPathProvider
def fromJar(path: PathType): JarProvider
def fromDir(path: PathType): DirectoryProvider
def fromExtDir(path: PathType): MultiProvider
def fromModule(moduleId: ModuleID): ClassRepProvider
}
object Provider extends ProviderCreation {
def fromUrls(urls: Seq[URL]): MultiProvider = ???
def fromUrl(url: URL): UrlProvider = ???
def fromPath(path: PathType): SinglePathProvider = ???
def fromClassPath(classPath: String): ClassPathProvider = ???
def fromJar(path: PathType): JarProvider = ???
def fromDir(path: PathType): DirectoryProvider = ???
def fromExtDir(path: PathType): MultiProvider = ???
def fromModule(moduleId: ModuleID): ClassRepProvider = ???
}
trait ClassRepFile {
def name: String
def className: String
def lastModified: Long
}
trait ClassSourceFile extends ClassRepFile {
def chars: Array[Char]
}
trait ClassBinaryFile extends ClassRepFile {
def bytes: Array[Byte]
}
sealed abstract class ClassRep {
def source: ClassSourceFile
def binary: ClassBinaryFile
def className = if (hasBinary) binary.className else source.className
def hasBinary = binary ne NoClassBinaryFile
def hasSource = source ne NoClassSourceFile
def sourceOnly = hasSource && !hasBinary
def binaryOnly = hasBinary && !hasSource
def isEmpty = !hasBinary && !hasSource
def orElse[T](alt: => ClassRep): ClassRep = this
def foreach[U](f: ClassRep => U): Unit = f(this)
def withFilter(p: ClassRep => Boolean): ClassRep = if (p(this)) this else NoClassRep
def filter(p: ClassRep => Boolean): ClassRep = if (p(this)) this else NoClassRep
override def toString = className + ((source, binary))
}
final case class SourceRep(source: ClassSourceFile) extends ClassRep { ... }
final case class BinaryRep(binary: ClassBinaryFile) extends ClassRep { ... }
final case class DualClassRep(source: ClassSourceFile, binary: ClassBinaryFile) extends ClassRep { ... }
final case object NoClassRep extends ClassRep { ... }
trait ClassRepProvider {
/** The class representation for the given name, or NoClassRep
* if unknown.
*/
def classRep(name: String): ClassRep
/** Whether the given class name can be supplied if requested,
* assuming that is known. Otherwise, false.
*/
def providesClass(name: String): Boolean
}
trait ClassLoadingProvider extends ClassRepProvider {
/** The ClassLoader used by this provider.
*/
def classLoader: ClassLoader
/** True if this provider can supply a class representation for
* the given name.
*/
def classInstance(name: String): Class[_]
}
trait ClassDefiningProvider extends ClassLoadingProvider {
/** Define a class based on the given name and bytecode.
*/
def defineClass(name: String, bytes: Array[Byte]): Class[_]
}
trait EnumerableProvider extends ClassRepProvider {
/** All the classes in this package.
*/
def classes: Iterable[ClassRep]
}
trait PackageProvider extends EnumerableProvider {
/** The name of this package.
*/
def packageName: String
/** The providers for this package's immediate subpackages.
*/
def packages: Iterable[PackageProvider]
}
/*** Drifting into a sampling of implementations ***/
trait MultiProvider extends BaseProvider {
def providers: List[ClassRepProvider]
def flatten: List[ClassRepProvider] = providers flatMap {
case mp: MultiProvider => mp.flatten
case p => List(p)
}
}
trait SerialClassProvider extends MultiProvider {
def classRep(name: String) = {
@tailrec def loop(xs: List[ClassRepProvider]): ClassRep = xs match {
case Nil => NoClassRep
case x :: xs => if (x providesClass name) x classRep name else loop(xs)
}
loop(providers)
}
def providesClass(name: String) = providers exists (_ providesClass name)
}
class ForwardingPackageProvider(underlying: PackageProvider) extends PackageProvider {
def classes: Iterable[ClassRep] = underlying classes
def classRep(name: String): ClassRep = underlying classRep name
def providesClass(name: String): Boolean = underlying providesClass name
def packageName: String = underlying packageName
def packages: Iterable[PackageProvider] = underlying packages
}
class FilteredPackageProvider(underlying0: PackageProvider, p: String => Boolean) extends ForwardingPackageProvider(underlying0) {
override def classRep(name: String): ClassRep = if (p(name)) super.classRep(name) else NoClassRep
override lazy val classes: Iterable[ClassRep] = super.classes filter (c => p(c.className))
override lazy val packages: Iterable[PackageProvider] = super.packages map (pkg => new FilteredPackageProvider(pkg, p))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment