Created
January 27, 2012 16:27
-
-
Save paulp/1689615 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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