Please refer to the Find-Primes example before starting with this example.

First, define the CnC graph for the partition string example:

object PartitionStringCncDefinition {
  def main(args: Array[String]): Unit = {
    ApplicationName("PartitionString")
    TargetPackage("partitionstring")
    TargetDirectory("partitionstring")

    Comment("Item Collections")
    ItemCollection[String, String]("input")
    ItemCollection[String, String]("span")
    ItemCollection[String, String]("results")

    Comment("Tag Collections")
    TagCollection[String]("stringTag")
    TagCollection[String]("spanTags")

    Comment("Step Prescriptions")
    Presription("singletonTag", List("createSpan"))
    Presription("spanTags", List("processSpan"))

    Comment("Step Dependences")
    StepDependence("createSpan", List[String]("input"), List("spanTags", "span"))
    StepDependence("processSpan", List[String]("span"), List("results"))

    Comment("Environment Collections")
    EnvironmentDependence(
      List("input", "stringTag"),
      List("results")
    )
  }
}

This graph is a little more interesting than the Find-Primes example since it has two Steps: createSpan and processSpan. createSpan produces Items for the span Item Collection. This in turn triggers the prescription of the processSpan step which writes results to the results Item Collection. The environment reads off these values from the results Item Collection.

Diagrammatically, this is how the CnC graph looks:
(Image from Kathleen Knobe's CnC Tutorial)

Next, run the CnC-Scala translator:

cnc_scala_translate PartitionStringCncDefinition

Next, we need to provide the implementations for the Steps using the generated templates (as explained in the Find-Primes example).

Note for experienced CnC users: the implementation of the compute() method reads the input dependences on values from the Item Collections without explicitly stating its dependences in a ready() or awaitsList() method as required in some of the other CnC implementations.

package partitionstring

import edu.rice.cnc.api._
import java.lang.String
import util.continuations.cps

class UserCreateSpanStep extends CreateSpanStep {
  def compute(
               tag: String,
               inInput: InputCollection[String, String],
               outSpanTags: TagCollection[String],
               outSpan: OutputCollection[String, String]
               ): Unit@cps[Any] = {

    // Get input string
    val in: String = inInput.get(tag)

    if (in.length() != 0) {
      var ch: Char = in.charAt(0)
      var len: Int = 0
      var i: Int = 0
      var j: Int = 0
      while (i < in.length()) {
        if (in.charAt(i) == ch) {
          i += 1
          len += 1
        } else {
          val jStr = String.valueOf(j)
          outSpan.put(jStr, in.substring(j, j + len))
          outSpanTags.put(jStr)
          ch = in.charAt(i)
          len = 0
          j = i
        }
      }
      val jStr: String = String.valueOf(j)
      outSpan.put(jStr, in.substring(j, j + len))
      outSpanTags.put(jStr)
    }
  }
}

class UserProcessSpanStep extends ProcessSpanStep {
  def compute(
               tag: String,
               inSpan: InputCollection[String, String],
               outResults: OutputCollection[String, String]
               ): Unit@cps[Any] = {

    val toProcess = inSpan.get(tag)

    if ((toProcess.length() % 2) != 0) {
      outResults.put(tag, toProcess)
    }
  }
}

Running this program with an input of aaaaaabbbbbccddddddsssrrrrrw should produce the following output:

Contents of Collection'results'
  19=sss
  22=rrrrr
  27=w
  6=bbbbb
HabaneroRuntime:
  num workers=4
  executor service=jsr166y.ForkJoinPool@647109c4[Terminating, parallelism = 4, size = 4, active = 4, running = 4, steals = 6, tasks = 0, submissions = 0]
  async instances=9
  activity instances=9