I don't use Scala very often and consider myself to be quite a beginner with it. It has been a long while since I worked with it. So when I heard a recent request to help someone with the generation of XML data for a project, I decided to use the opportunity to brush up on my Scala and try out the support for XML.
In short, the solution I came up with is not bad and relatively short. It likely could be done better though. What I found interesting is that it took me an hour or two to sort out some of the details. The somewhat embarrassing part is that someone did some work in MS Word and produced a 90% solution in a much shorter time though. In this case, the elegance of the language and solution was a bigger draw to me than the much lower tech but practical solution. I find myself somewhat embarrassed by this but at least it did help me brush up on things a bit.
Another somewhat negative note is that it sounds like (per some messages on the Scala site) the XML support is somewhat an unwanted stepchild. It sounded like those closely involved with the languages evolution would prefer to move to either the string interpolation or something similar/related to it. I think a number of people indicated problems with the way it works now. I didn't really take the time to understand the details of the arguments.
I will say that the XML support was not 100% straight forward. Things went easier once I gave up trying to perform what I think would be described as partial String interpolation in attribute text values. In my final result, I end up pushing in "completed" attribute values instead of trying to do something like replacements in the middle of the overall text attribute value.
In other words, in the user_template definition below;
DisplayName={sdisplayName}
works while something like:
DisplayName="{lastName}, {firstName}"
did not work.
So my final code had to generate each attribute value in its entirety which was then passed into the function and used to replace the attribute text place holder in the XML.
So even if this didn't work exactly as I had hopped, it was still useful. If the group managing the language are able to provide functionality that is more natural and powerful though, it would be immensely useful. I am very grateful for the work they are doing.
I also want to note that I was working on this in Eclipse Kepler Release 2 and it worked pretty well. More nice work..
import scala.io.Source._
import scala.xml.Node
object fmtdata extends App
{
def outer_template(users : List[Node]) =
<PrincipalMappingConfiguration
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Entries>
<PrincipalMappingEntry
SourceAddress="https://test.org/"
DestinationAddress="https://test.org/teams/">
<MappingInformation>
<Mappings>
{users}
</Mappings>
</MappingInformation>
</PrincipalMappingEntry>
</Entries>
</PrincipalMappingConfiguration>;
def user_template(sacctname : String, dacctname : String, email: String, sdisplayName : String, ddisplayName : String) =
<PrincipalMapping>
<SourcePrincipal AccountName={sacctname}
UserInfoId="0"
DisplayName={sdisplayName}
Email={email} Title="" PrincipalType="User" />
<DestinationPrincipal AccountName={dacctname}
UserInfoId="0"
DisplayName={ddisplayName}
Email={email}
Title=""
PrincipalType="User"
Department="" />
</PrincipalMapping>;
val header = "<?xml version=\"1.0\"?>";
val infile = fromFile("c:\\temp\\users.csv")
val lines = infile.getLines().toList map { _.split(",") }
infile.close()
var users: List[Node] = List[Node]()
// lname, fname, vcid, eadid
lines.foreach{ f =>
users = users ++
(user_template("i:0#.w|org\\"++f(2), /* source id */
"i:0#.w|dir\\" ++ f(3), /* dest id */
f(2) ++ "@test.org", /* email */
f(1) ++ " " ++ f(0), /* source name */
f(0) ++ ", " ++ f(1))); /* dest name*/
}
println( header )
println( outer_template(users) )
}
The input file, users.csv would look something like this (dummy data):
myLastName1,myFirstName1,myDomainAcctA1,myDomainAcctB1
myLastName2,myFirstName2,myDomainAcctA2,myDomainAcctB2
myLastName3,myFirstName3,myDomainAcctA3,myDomainAcctB3
myLastName4,myFirstName4,myDomainAcctA4,myDomainAcctB4
smith,myfirstname,mysmith,smithm
The output would then look something like:
<?xml version="1.0"?>
<PrincipalMappingConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Entries>
<PrincipalMappingEntry SourceAddress="https://test.org/" DestinationAddress="https://test.org/teams/">
<MappingInformation>
<Mappings>
<PrincipalMapping>
<SourcePrincipal AccountName="i:0#.w|org\myDomainAcctA1" UserInfoId="0" DisplayName="myFirstName1 myLastName1" Email="myDomainAcctA1@test.org" Title="" PrincipalType="User"/>
<DestinationPrincipal AccountName="i:0#.w|dir\myDomainAcctB1" UserInfoId="0" DisplayName="myLastName1, myFirstName1" Email="myDomainAcctA1@test.org" Title="" PrincipalType="User" Department=""/>
</PrincipalMapping><PrincipalMapping>
<SourcePrincipal AccountName="i:0#.w|org\myDomainAcctA2" UserInfoId="0" DisplayName="myFirstName2 myLastName2" Email="myDomainAcctA2@test.org" Title="" PrincipalType="User"/>
<DestinationPrincipal AccountName="i:0#.w|dir\myDomainAcctB2" UserInfoId="0" DisplayName="myLastName2, myFirstName2" Email="myDomainAcctA2@test.org" Title="" PrincipalType="User" Department=""/>
</PrincipalMapping><PrincipalMapping>
<SourcePrincipal AccountName="i:0#.w|org\myDomainAcctA3" UserInfoId="0" DisplayName="myFirstName3 myLastName3" Email="myDomainAcctA3@test.org" Title="" PrincipalType="User"/>
<DestinationPrincipal AccountName="i:0#.w|dir\myDomainAcctB3" UserInfoId="0" DisplayName="myLastName3, myFirstName3" Email="myDomainAcctA3@test.org" Title="" PrincipalType="User" Department=""/>
</PrincipalMapping><PrincipalMapping>
<SourcePrincipal AccountName="i:0#.w|org\myDomainAcctA4" UserInfoId="0" DisplayName="myFirstName4 myLastName4" Email="myDomainAcctA4@test.org" Title="" PrincipalType="User"/>
<DestinationPrincipal AccountName="i:0#.w|dir\myDomainAcctB4" UserInfoId="0" DisplayName="myLastName4, myFirstName4" Email="myDomainAcctA4@test.org" Title="" PrincipalType="User" Department=""/>
</PrincipalMapping><PrincipalMapping>
<SourcePrincipal AccountName="i:0#.w|org\mysmith" UserInfoId="0" DisplayName="myfirstname smith" Email="mysmith@test.org" Title="" PrincipalType="User"/>
<DestinationPrincipal AccountName="i:0#.w|dir\smithm" UserInfoId="0" DisplayName="smith, myfirstname" Email="mysmith@test.org" Title="" PrincipalType="User" Department=""/>
</PrincipalMapping>
</Mappings>
</MappingInformation>
</PrincipalMappingEntry>
</Entries>
</PrincipalMappingConfiguration>
No comments:
Post a Comment