public void TransformClaims(
            ref SecurityPropertyCollection incomingClaims,
            ref SecurityPropertyCollection corporateClaims,
            ref SecurityPropertyCollection outgoingClaims,
            ClaimTransformStage transformStage,
            string issuer,
            string target)
        {
            // Create the SamlBridge CTM's trace listener.
            TextWriterTraceListener twtlSamlBridgeCtmTraceListener =
                new TextWriterTraceListener(Constants.PATH_SAML_BRIDGE_CTM_TRACE_FILE);

            if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
            {
                Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                    Constants.TRCI_CLAIM_TRANSFORMATION_MODULE_ENTERED);
            }

            // We only perform any mapping action in the pre-processing stage, so return
            // immediately if we are not at this stage.
            if (transformStage != ClaimTransformStage.PreProcessing)
            {
                if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                {
                    Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                        Constants.TRCI_NOT_PREPROCESSING_STAGE);
                }
                return;
            }

            // If incomingClaims is null, then there is nothing to map. corporateClaims is
            // probably populated, in which case ADFS has previously authenticated the user and
            // is reusing the already-mapped SAML assertion from the user's cookie.
            if ((incomingClaims != null) && (incomingClaims.Count > 0))
            {
                if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                {
                    Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                        Constants.TRCI_INCOMING_CLAIMS_FOUND);
                }

                // Validate that the SAML is as expected, i.e. that we have a UPN in the
                // incoming claims.
                int iUpnClaimIndex = FindClaim(incomingClaims, WebSsoClaimType.Upn);
                if (iUpnClaimIndex == -1)
                {
                    if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceError)
                    {
                        Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                            Constants.TRCE_NO_INCOMING_UPN_CLAIM_FOUND);
                    }

                    throw new SamlBridgeCctException(Constants.EXC_NO_INCOMING_UPN_CLAIM);
                }

                SecurityProperty spUpnClaim = incomingClaims[iUpnClaimIndex];

                // Read out the UID from the UPN claim
                string sUid = spUpnClaim.Value;

                if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                {
                    Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                        Constants.TRCI_INCOMING_UPN_CLAIM_VALUE, sUid);
                }

                // Remove the UPN claim from the collection - we will replace it with the real
                // UPN claim later.
                incomingClaims.RemoveAt(iUpnClaimIndex);

                #region ADFS AMPERSAND WORKAROUND
                // At the time of writing there appears to be a problem in ADFS whereby any
                // ampersand, less than, greater than, quote or apostrophe character contained
                // in the value of a claim in the authenticated SAML causes the ADFS Web Agent
                // to throw an exception.
                //
                // The following temporary workaround replaces any such characters in custom
                // claim values with a plain text equivalent, or, in the case of the quote and
                // apostrophe, nothing.
                for (int i = 0; i < incomingClaims.Count; i++)
                {
                    SecurityProperty spThisClaim     = incomingClaims[i];
                    string           sThisClaimValue = spThisClaim.Value;
                    if (sThisClaimValue.IndexOf("&") != -1)
                    {
                        if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                        {
                            Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                                Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "&",
                                spThisClaim.Name);
                        }

                        sThisClaimValue = sThisClaimValue.Replace("&", "and");
                    }

                    if (sThisClaimValue.IndexOf("<") != -1)
                    {
                        if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                        {
                            Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                                Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "<",
                                spThisClaim.Name);
                        }

                        sThisClaimValue = sThisClaimValue.Replace("<", "lessthan");
                    }

                    if (sThisClaimValue.IndexOf(">") != -1)
                    {
                        if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                        {
                            Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                                Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, ">",
                                spThisClaim.Name);
                        }

                        sThisClaimValue = sThisClaimValue.Replace(">", "greaterthan");
                    }

                    if (sThisClaimValue.IndexOf("\"") != -1)
                    {
                        if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                        {
                            Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                                Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "\"",
                                spThisClaim.Name);
                        }

                        sThisClaimValue = sThisClaimValue.Replace("\"", "");
                    }

                    if (sThisClaimValue.IndexOf("'") != -1)
                    {
                        if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                        {
                            Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                                Constants.TRCI_PERFORMING_CLAIM_VALUE_SUBSTITUTION, "'",
                                spThisClaim.Name);
                        }

                        sThisClaimValue = sThisClaimValue.Replace("'", "");
                    }

                    if (spThisClaim.Value != sThisClaimValue)
                    {
                        SecurityProperty spNewProperty =
                            SecurityProperty.CreateCustomClaimProperty(
                                spThisClaim.Name, sThisClaimValue);

                        incomingClaims[i] = spNewProperty;
                    }
                }
                #endregion

                // Determine how the user's UPN should be obtained. If the SamlBridge registry
                // value ResourceDomainDirectoryPath exists and has a non-empty value, then the
                // UPN is obtained by performing a local LDAP search based on the path defined
                // by the value of ResourceDomainDirectoryPath for a user whose UID corresponds
                // to the UID extracted from the incoming claim, and taking the UPN of this
                // user.
                //
                // Otherwise, if ResourceDomainDirectoryPath does not exist or has an empty
                // value, then the value of registry value ResourceDomainUpnSuffix is used to
                // create the UPN directly from the UID. If ResourceDomainUpnSuffix exists and
                // has a non-empty value, the UPN is generated by appending an ampersand
                // followed by the value of ResourceDomainUpnSuffix to the UID. If
                // ResourceDomainUpnSuffix does not exist or is empty, the unadorned UID is used
                // as the UPN.
                string sUpn = string.Empty;
                if (ResourceDomainDirectoryPath.Length != 0)
                {
                    if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                    {
                        Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                            Constants.TRCI_UPN_BY_DIRECTORY_LOOKUP);
                    }

                    sUpn = GetUpnByUid(sUid, incomingClaims);
                }
                else
                {
                    if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                    {
                        Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                            Constants.TRCI_UPN_BY_UID_SUFFIXING, ResourceDomainUpnSuffix);
                    }

                    if (ResourceDomainUpnSuffix.Length != 0)
                    {
                        sUpn = string.Format(
                            Universal.SFMT_USER_PRINCIPAL_NAME,
                            sUid,
                            Universal.UPN_SUFFIX_PREFIX,
                            ResourceDomainUpnSuffix);
                    }
                    else
                    {
                        sUpn = sUid;
                    }
                }

                if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceInfo)
                {
                    Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                        Constants.TRCI_OUTGOING_RESOURCE_DOMAIN_UPN, sUpn);
                }

                // Insert a new UPN claim into the incoming claims collection, containing the
                // newly generated UPN.
                incomingClaims.Add(SecurityProperty.CreateUserPrincipalNameProperty(sUpn));
            }
            else
            {
                if (Fujitsu.SamlBridge.Cct.Trace.s_trswSamlBridgeCtmPath.TraceWarning)
                {
                    Fujitsu.SamlBridge.Cct.Trace.WriteLine(
                        Constants.TRCW_NO_INCOMING_CLAIMS_FOUND);
                }
            }
        }