forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphonebook3.scala
81 lines (57 loc) · 2.44 KB
/
phonebook3.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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 @ <entry><name>{ Text(Name) }</name>{ ch1 @ _* }</entry> =>
var updated = false;
val ch2 = for(c <- ch1) yield c match { // does it have the phone number?
case y @ <phone>{ _* }</phone> if y \ "@where" == Where =>
updated = true
<phone where={ Where }>{ newPhone }</phone>
case y => y
}
if( !updated ) { // no, so we add as first entry
<entry>
<name>{ Name }</name>
<phone where={ Where }>{ newPhone }</phone>
{ ch1 }
</entry>
} else { // yes, and we changed it as we should
<entry>
{ ch2 }
</entry>
}
// end case x @ <entry>...
// other entries are copied without changing them
case x =>
x
}
} ; // for ... yield ... returns an Iterator[Node]
// decompose phonebook, apply updates
phonebook match {
case <phonebook>{ ch @ _* }</phonebook> =>
<phonebook>{ copyOrChange( ch.iterator ) }</phonebook>
}
}
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 ));
}
}