Parsing the ProjectRename Method
The Project Renamer PDS extender for Microsoft® Office Project Server 2003 uses the RenameProject function to parse the <ProjectRename> node in the XML request and to call the helper functions that do the work of renaming a project.
Following is the RenameProject signature:
Public Function RenameProject( _
ByVal oNode As MSXML2.IXMLDOMNode) _
As Long
XMLRequest passes the following XML node to RenameProject in the oNode parameter. The <ProjectRename> node can have one or more <Project> nodes.
<ProjectRename>
<Project>
<ProjectID></ProjectID>
<NewName></NewName>
</Project>
<Project>
<ProjectID></ProjectID>
<NewName></NewName>
</Project>
. . .
</ProjectRename>
RenameProject parses all of the <Project> child nodes, and then creates a comma-separated list of the ProjectID values in the sIDs variable and makes the following basic checks for errors for each Project in the request. If any value is incorrect, the entire ProjectRename request fails with the appropriate STATUS code.
- Check the ProjectID value for an empty string
- If the ProjectID string is numeric, use CLng to convert it to a variable of type Long.
- Don't continue if ProjectID is less than 1 (the minimum value of PROJ_ID in the database).
- Call the Validate function for each NewName value, to make sure there are no invalid characters in the name.
RenameProject creates another comma-separated list of the valid NewName values in the sNames variable, where NewName string values are delineated by single quotation marks.
Note Validate uses the INVALID_CHAR constant, which is defined in Constants.bas as the following set of characters for the U.S. keyboard:
Public Const INVALID_CHAR = ".\""/:;|?'<>*"
If one NewName value is invalid, then the whole call fails and RenameProject returns STATUS_PROJECT_NAME_INVALID. You can add other characters to the set; it might be a different set of characters for other language keyboard layouts.
If each NewName value is valid, RenameProject also calls ProduceSQLQuery and adds the resulting SQL query string with the project name and ID to the sQuery variable.
Dim oProjNodes As IXMLDOMNodeList
Dim oProjNode As IXMLDOMNode
Dim nProjID As Long
Dim sNewName As String
Dim result As Boolean
Dim sQuery As String
Dim lStatus As Long
Dim numIDs As Long
lStatus = STATUS_OK
Dim sNames As String, sIDs As String
result = oNode.hasChildNodes()
If (result = True) Then
sQuery = ""
numIDs = 0
Set oProjNodes = oNode.selectNodes("Project")
For Each oProjNode In oProjNodes
Dim sProjID As String
sProjID = GetNodeValue(oProjNode, "ProjectID")
If sProjID = "" Then
lStatus = rsNoValuesSpecified
GoTo PrepareReply
End If
If IsNumeric(sProjID) Then
nProjID = CLng(sProjID)
Else
lStatus = rsProjectIDInvalid
GoTo PrepareReply
End If
If nProjID < MIN_PROJECT_ID Then
lStatus = rsProjectIDInvalid
GoTo PrepareReply
Else
sNewName = GetNodeValue(oProjNode, "NewName")
End If
If Validate(sNewName) Then
' Update SQL Query
sQuery = sQuery & ProduceSQLQuery(sNewName, nProjID) & vbNewLine
Else
lStatus = STATUS_PROJECT_NAME_INVALID
GoTo PrepareReply
End If
sIDs = sIDs & "," & nProjID
numIDs = numIDs + 1
sNames = sNames & ",'" & sNewName & "'"
Next oProjNode
sIDs = Right(sIDs, Len(sIDs) - 1)
sNames = Right(sNames, Len(sNames) - 1)
' Connect and run query, and set lStatus
. . .
Else
lStatus = STATUS_INVALID_REQUEST
GoTo PrepareReply
End If
PrepareReply:
RenameProject = lStatus
End Function
After the sQuery, sIDs, and sNames strings are set for all <Project> nodes in the XML request, RenameProject then connects to the Project Server database. Before running the SQL query to change the project names, you should check that every project ID actually matches an existing project, and you must make sure no duplicate names will be created. The user must also have the necessary permission to change each project name, and none of the projects to be renamed can be checked out. The whole request fails if any of the tests fail. The CheckProjIDs, CheckForDuplicates, CheckForPermission, and CheckForCheckedOut functions use the sIDs and sNames strings to check all of the projects that would be affected.
. . .
' Connect and run queries; set lStatus if any tests fail
CreateConnection
If Not CheckProjIDs(sIDs, numIDs) Then
lStatus = rsProjectNotFound
ElseIf Not CheckForDuplicates(sNames) Then
lStatus = rsProjectNameMultiplesInvalid
ElseIf Not CheckForPermission(sIDs) Then
lStatus = STATUS_ACCESS_DENIED
ElseIf Not CheckForCheckedOut(sIDs) Then
lStatus = STATUS_PROJECT_CHECKEDOUT
Else
ExecuteSQLQuery sQuery
End If
DestroyConnection
. . .
For an explanation of how ProduceSQLQuery works, and of the queries in the CheckProjIDs, CheckForDuplicates, CheckForPermission, and CheckForCheckedOut functions, see Creating the Database Queries.
Note The CMain.cls file in the Project 2003: Project Renamer PDS Extender (pj11pdsxRenamer.exe) download contains the implementation of the SQL query functions, and of the CreateConnection, DestroyConnection, and ExecuteSQLQuery functions.