package phonebook;
object phonebook3 {
import scala.xml.{Elem, Node, Text} ;
import scala.xml.PrettyPrinter ;
import Node.NoAttributes ;
/* this method "changes" (returns an updated copy) of the phonebook when the
* entry for Name exists. If it has an attribute "where" whose value is equal to the
* parameter Where, it is changed, otherwise, it is added.
*/
def change ( phonebook:Node, Name:String, Where:String, newPhone:String ) = {
/** this nested function walks through tree, and returns an updated copy of it */
def copyOrChange ( ch: Iterator[Node] ) = {
import xml.Utility.{trim,trimProper} //removes whitespace nodes, which are annoying in matches
for( val c <- ch ) yield
trimProper(c) match {
// if the node is the particular entry we are looking for, return an updated copy
case x @ { Text(Name) }{ ch1 @ _* } =>
var updated = false;
val ch2 = for(val c <- ch1) yield c match { // does it have the phone number?
case y @ { _* } if y \ "@where" == Where =>
updated = true
{ newPhone }
case y => y
}
if( !updated ) { // no, so we add as first entry
{ Name }
{ newPhone }
{ ch1 }
} else { // yes, and we changed it as we should
{ ch2 }
}
// end case x @ ...
// other entries are copied without changing them
case x =>
x
}
} ; // for ... yield ... returns an Iterator[Node]
// decompose phonebook, apply updates
phonebook match {
case { ch @ _* } =>
{ copyOrChange( ch.elements ) }
}
}
val pb2 =
change( phonebook1.labPhoneBook, "John", "work", "+41 55 555 55 55" );
val pp = new PrettyPrinter( 80, 5 );
def main( args:Array[String] ) = {
Console.println("---before---");
Console.println( pp.format( phonebook1.labPhoneBook ));
Console.println("---after---");
Console.println( pp.format( pb2 ));
}
}