alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (Files.scala)

This example Scala source code file (Files.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

abstractfile, abstractfile, boolean, filedependencies, int, io, printstream, set, string, string, t, t, tracker, tracker, unit

The Scala Files.scala source code

package scala.tools.nsc
package dependencies

import java.io.{InputStream, OutputStream, PrintStream, InputStreamReader, BufferedReader}
import io.{AbstractFile, PlainFile, VirtualFile}

import scala.collection._


trait Files { self : SubComponent =>

  class FileDependencies(val classpath: String) {
    import FileDependencies._

    class Tracker extends mutable.OpenHashMap[AbstractFile, mutable.Set[AbstractFile]] {
      override def default(key: AbstractFile) = {
        this(key) = new mutable.HashSet[AbstractFile]
        this(key)
      }
    }

    val dependencies = new Tracker
    val targets =  new Tracker

    def isEmpty = dependencies.isEmpty && targets.isEmpty

    def emits(source: AbstractFile, result: AbstractFile) = 
      targets(source) += result
    def depends(from: AbstractFile, on: AbstractFile) = 
      dependencies(from) += on

    def reset(file: AbstractFile) = dependencies -= file
    
    def cleanEmpty = {
      dependencies foreach {case (_, value) =>
                               value retain (x => x.exists && (x ne removedFile))}
      dependencies retain ((key, value) => key.exists && !value.isEmpty)
      targets foreach {case (_, value) => value retain (_.exists)}
      targets retain ((key, value) => key.exists && !value.isEmpty)
    }

    def containsFile(f: AbstractFile) = targets.contains(f.absolute)        

    def invalidatedFiles(maxDepth: Int) = {
      val direct = new mutable.HashSet[AbstractFile]

      for ((file, products) <- targets) {
        // This looks a bit odd. It may seem like one should invalidate a file
        // if *any* of its dependencies are older than it. The forall is there
        // to deal with the fact that a) Some results might have been orphaned
        // and b) Some files might not need changing. 
        direct(file) ||= products.forall(d => d.lastModified < file.lastModified)
      }

      val indirect = dependentFiles(maxDepth, direct)

      for ((source, targets) <- targets  
           if direct(source) || indirect(source) || (source eq removedFile)) {
        targets foreach (_.delete)
        targets -= source
      }

      (direct, indirect)
    }

    /** Return the set of files that depend on the given changed files.
     *  It computes the transitive closure up to the given depth.
     */
    def dependentFiles(depth: Int, changed: Set[AbstractFile]): Set[AbstractFile] = {
      val indirect = new mutable.HashSet[AbstractFile]
      val newInvalidations = new mutable.HashSet[AbstractFile]

      def invalid(file: AbstractFile) =
        indirect(file) || changed(file) || (file eq removedFile)

      def go(i: Int) : Unit = if(i > 0) {
        newInvalidations.clear
        for((target, depends) <- dependencies if !invalid(target);
            d <- depends)
          newInvalidations(target) ||= invalid(d)

        indirect ++= newInvalidations
        if (!newInvalidations.isEmpty) go(i - 1)
      }

      go(depth)

      indirect --= changed
    }

    def writeTo(file: AbstractFile, fromFile: AbstractFile => String): Unit = 
      writeToFile(file)(out => writeTo(new PrintStream(out), fromFile))
    
    def writeTo(print: PrintStream, fromFile: AbstractFile => String): Unit = {
      def emit(tracker: Tracker) =
        for ((f, ds) <- tracker; d <- ds) print.println(fromFile(f) + arrow + fromFile(d))
      
      cleanEmpty
      print.println(classpath)
      print.println(separator)
      emit(dependencies)
      print.println(separator)
      emit(targets)
    }
  }

  object FileDependencies {
    private val separator:String = "-------"
    private val arrow = " -> "
    private val removedFile = new VirtualFile("removed")
    
    private def validLine(l: String) = (l != null) && (l != separator)

    def readFrom(file: AbstractFile, toFile: String => AbstractFile): Option[FileDependencies] =
      readFromFile(file) { in =>
        val reader = new BufferedReader(new InputStreamReader(in))
        val it = new FileDependencies(reader.readLine)
        
        def readLines(valid: Boolean)(f: (AbstractFile, AbstractFile) => Unit): Boolean = {
          var continue = valid
          var line: String = null
          while (continue && {line = reader.readLine; validLine(line)}) { 
            line.split(arrow) match {
              case Array(from, on) => f(toFile(from), toFile(on))
              case _ =>
                global.inform("Parse error: Unrecognised string " + line)
                continue = false
            }
          }
          continue
        }
        
        reader.readLine

        val dResult = readLines(true)(
          (_, _) match {
            case (null, _)          => // fromFile is removed, it's ok
            case (fromFile, null)   =>
              // onFile is removed, should recompile fromFile
              it.depends(fromFile, removedFile) 
            case (fromFile, onFile) => it.depends(fromFile, onFile)
          })
        
        readLines(dResult)(
          (_, _) match {
            case (null, null)             =>
              // source and target are all removed, it's ok
            case (null, targetFile)       =>
              // source is removed, should remove relative target later
              it.emits(removedFile, targetFile)
            case (_, null)                =>
              // it may has been cleaned outside, or removed during last phase
            case (sourceFile, targetFile) => it.emits(sourceFile, targetFile)
          })
          
        Some(it)
      }
  }

  def writeToFile[T](file: AbstractFile)(f: OutputStream => T) : T = {
    val out = file.bufferedOutput
    try {
      f(out) 
    } finally {
      out.close
    }
  }

  def readFromFile[T](file: AbstractFile)(f: InputStream => T) : T = {
    val in = file.input
    try{
      f(in)
    } finally {
      in.close
    }
  }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala Files.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.