// 按照字段修改权限定义,合并新旧两个 MARC 记录 // parameters: // strDefaultOperation insert/replace/delete 之一或者逗号间隔组合 // return: // -1 出错 // 0 成功 // 1 有部分修改要求被拒绝 public static int MergeOldNew( string strDefaultOperation, string strFieldNameList, string strOldMarc, ref string strNewMarc, out string strComment, out string strError) { strError = ""; strComment = ""; int nRet = 0; if (string.IsNullOrEmpty(strOldMarc) == true && string.IsNullOrEmpty(strNewMarc) == true) return 0; #if NO bool bNew = false; bool bDelete = false; bool bChange = false; if (string.IsNullOrEmpty(strAction) == true) { bNew = true; bDelete = true; bChange = true; } else { bNew = StringUtil.IsInList("new", strAction); bDelete = StringUtil.IsInList("delete", strAction); bChange = StringUtil.IsInList("change", strAction); } #endif string strOldHeader = ""; string strNewHeader = ""; string strOldBody = ""; string strNewBody = ""; SplitMarc(strOldMarc, out strOldHeader, out strOldBody); SplitMarc(strNewMarc, out strNewHeader, out strNewBody); if (strOldHeader.Length < 24) strOldHeader = strOldHeader.PadRight(24, '?'); if (strNewHeader.Length < 24) strNewHeader = strNewHeader.PadRight(24, '?'); #if NO FieldNameList list = new FieldNameList(); nRet = list.Build(strFieldNameList, out strError); if (nRet == -1) { strError = "字段权限定义 '" + strFieldNameList + "' 不合法: " + strError; return -1; } #endif OperationRights rights_table = new OperationRights(); nRet = rights_table.Build(strFieldNameList, strDefaultOperation, out strError); if (nRet == -1) { strError = "字段权限定义 '" + strFieldNameList + "' 不合法: " + strError; return -1; } var differ = new MarcDiffer(); var builder = new MarcDiffBuilder(differ); var result = builder.BuildDiffModel(strOldBody, strNewBody); Debug.Assert(result.OldText.Lines.Count == result.NewText.Lines.Count, ""); /* public enum ChangeType { Unchanged, Deleted, Inserted, Imaginary, Modified } * */ // 字段名如果最后增加了一个 ! 字符,表示这是因为 856 权限原因被拒绝操作的字段。如果 856 字段名后面没有 ! 字符,则表示是因为 fieldnamelist 定义缘故被拒绝的 // 被拒绝插入的字段名 List<string> denied_insert_fieldnames = new List<string>(); // 被拒绝删除的字段名 List<string> denied_delete_fieldnames = new List<string>(); // 被拒绝修改的字段名 List<string> denied_change_fieldnames = new List<string>(); bool bNotAccepted = false; List<string> fields = new List<string>(); for (int index = 0; index < result.NewText.Lines.Count; index ++ ) { var newline = result.NewText.Lines[index]; var oldline = result.OldText.Lines[index]; // 2013/11/18 if (string.IsNullOrEmpty(newline.Text) == true && string.IsNullOrEmpty(oldline.Text) == true) continue; string strNewFieldName = GetFieldName(newline.Text); // string strOldFieldName = GetFieldName(oldline.Text); if (newline.Type == ChangeType.Unchanged) { fields.Add(RemoveMask(newline.Text)); } else if (newline.Type == ChangeType.Inserted) { Debug.Assert(strNewFieldName != null, ""); // 注:有标记的字段不允许插入 bool bMask = HasMask(newline.Text); if (rights_table.InsertFieldNames.Contains(strNewFieldName) == true && bMask == false) fields.Add(newline.Text); else { denied_insert_fieldnames.Add(strNewFieldName + (bMask ? "!" : "")); bNotAccepted = true; } } else if (newline.Type == ChangeType.Modified) { Debug.Assert(strNewFieldName != null, ""); Debug.Assert(oldline.Type == ChangeType.Modified, ""); // 看新旧字段名是否都在可修改范围内 string strOldFieldName = GetFieldName(oldline.Text); Debug.Assert(strOldFieldName != null, ""); // 注:如果 new 有标记,说明如果替换后,前端看不到这种替换,所以不允许替换 // 如果 old 有标记,则替换会超越权限,等于删除了不应删除的 856 // 等于前端只能将能管辖的 856 改成新的也能管辖的状态才被允许 bool bMaskNew = HasMask(newline.Text); bool bMaskOld = HasMask(oldline.Text); bool bReserveOld = false; if (rights_table.ReplaceFieldNames.Contains(strNewFieldName) == true && rights_table.ReplaceFieldNames.Contains(strOldFieldName) == true ) { if (bMaskNew == false && bMaskOld == false) fields.Add(newline.Text); if (bMaskNew == true && bMaskOld == false) { bReserveOld = true; } if (bMaskNew == false && bMaskOld == true) { // 有时候这种情况: // 111 -> 删除 // 222 -> 2222 (修改内容) // 会被识别成 // 111 -> 2222 (修改内容) // 222 -> 删除 // 这样,第一个修改动作应该不接受。循环到后面,第二个修改正好被接受,所以总体上不会造成 222 重复 // 所以,第一个修改此时操作办法:old new 都进去 fields.Add(RemoveMask(oldline.Text)); fields.Add(newline.Text); } if (bMaskNew == true && bMaskOld == true) { bReserveOld = true; } } if (bReserveOld) { fields.Add(RemoveMask(result.OldText.Lines[index].Text)); // 依然采用修改前的值 bNotAccepted = true; denied_change_fieldnames.Add(strOldFieldName + (bMaskNew ? "!" : "")); } } else if (oldline.Type == ChangeType.Deleted) { string strOldFieldName = GetFieldName(oldline.Text); Debug.Assert(strOldFieldName != null, ""); // 注:有标记的字段不允许用于删除 bool bMask = HasMask(oldline.Text); if (rights_table.DeleteFieldNames.Contains(strOldFieldName) == false || bMask == true) { fields.Add(RemoveMask(oldline.Text)); // 不允许删除 // 当具有标记的时候,表示这是因为旧记录中的字段权限禁止当前用户获取,造成前端得不到这个字段,然后在提交保存的时候也就没有这个字段,并不是前端故意要删除这个字段,因而也就不要做 partial_denied 提示了 if (bMask == false) { bNotAccepted = true; denied_delete_fieldnames.Add(strOldFieldName + (bMask ? "!" : "")); } } else { // bNotAccepted = true; // BUG } } } StringBuilder text = new StringBuilder(4096); if (rights_table.ReplaceFieldNames.Contains("###") == true || rights_table.InsertFieldNames.Contains("###") == true) text.Append(strNewHeader); else { if (strNewHeader != strOldHeader) { bNotAccepted = true; denied_change_fieldnames.Add("###"); // ### 表示头标区 } text.Append(strOldHeader); } foreach (string s in fields) { if (string.IsNullOrEmpty(s) == true) continue; text.Append(s); text.Append((char)30); } if (denied_insert_fieldnames.Count > 0) strComment += "字段 " + StringUtil.MakePathList(denied_insert_fieldnames)+ " 被拒绝插入"; if (denied_delete_fieldnames.Count > 0) { if (string.IsNullOrEmpty(strComment) == false) strComment += " ; "; strComment += "字段 " + StringUtil.MakePathList(denied_delete_fieldnames) + " 被拒绝删除"; } if (denied_change_fieldnames.Count > 0) { if (string.IsNullOrEmpty(strComment) == false) strComment += " ; "; strComment += "字段 " + StringUtil.MakePathList(denied_change_fieldnames) + " 被拒绝修改"; } strNewMarc = text.ToString(); if (bNotAccepted == true) return 1; return 0; }
// 创建展示两个 MARC 记录差异的 HTML 字符串 // return: // -1 出错 // 0 成功 public static int DiffHtml( string strOldTitle, string strOldMarc, string strOldFragmentXml, string strOldImageFragment, string strNewTitle, string strNewMarc, string strNewFragmentXml, string strNewImageFragment, out string strHtml, out string strError) { strError = ""; strHtml = ""; // int nRet = 0; if (string.IsNullOrEmpty(strOldMarc) == true && string.IsNullOrEmpty(strNewMarc) == true) return 0; string strOldHeader = ""; string strNewHeader = ""; string strOldBody = ""; string strNewBody = ""; SplitMarc(strOldMarc, out strOldHeader, out strOldBody); SplitMarc(strNewMarc, out strNewHeader, out strNewBody); if (strOldHeader.Length < 24) strOldHeader = strOldHeader.PadRight(24, '?'); if (strNewHeader.Length < 24) strNewHeader = strNewHeader.PadRight(24, '?'); var marc_differ = new MarcDiffer(); var marc_builder = new MarcDiffBuilder(marc_differ); var marc_diff_result = marc_builder.BuildDiffModel(strOldBody, strNewBody); Debug.Assert(marc_diff_result.OldText.Lines.Count == marc_diff_result.NewText.Lines.Count, ""); /* public enum ChangeType { Unchanged, Deleted, Inserted, Imaginary, Modified } * */ StringBuilder strResult = new StringBuilder("\r\n<table class='marc'>", 4096); if (string.IsNullOrEmpty(strOldTitle) == false || string.IsNullOrEmpty(strNewTitle) == false) { string strLineClass = "header"; strResult.Append("\r\n<tr class='" + strLineClass + "'>"); strResult.Append(BuildHeaderHtml(false, strOldTitle)); strResult.Append(SEP); strResult.Append(BuildHeaderHtml(false, strNewTitle)); strResult.Append("\r\n</tr>"); } { string strLineClass = "header"; bool bModified = strOldHeader != strNewHeader; strResult.Append("\r\n<tr class='" + strLineClass + "'>"); strResult.Append(BuildHeaderHtml(bModified, strOldHeader)); strResult.Append(SEP); strResult.Append(BuildHeaderHtml(bModified, strNewHeader)); strResult.Append("\r\n</tr>"); } if (string.IsNullOrEmpty(strOldImageFragment) == false || string.IsNullOrEmpty(strNewImageFragment) == false) { string strLineClass = "header"; strResult.Append("\r\n<tr class='" + strLineClass + "'>"); strResult.Append(GetImageHtml(strOldImageFragment)); strResult.Append(SEP); strResult.Append(GetImageHtml(strNewImageFragment)); strResult.Append("\r\n</tr>"); } for (int index = 0; index < marc_diff_result.NewText.Lines.Count; index++) { var newline = marc_diff_result.NewText.Lines[index]; var oldline = marc_diff_result.OldText.Lines[index]; if (string.IsNullOrEmpty(newline.Text) == true && string.IsNullOrEmpty(oldline.Text) == true) continue; string strLineClass = "datafield"; strResult.Append("\r\n<tr class='" + strLineClass + "'>"); // 创建一个字段的 HTML 局部 三个 <td> strResult.Append(BuildFieldHtml( oldline.Type, oldline.Text)); strResult.Append(SEP); strResult.Append(BuildFieldHtml(newline.Type, newline.Text)); strResult.Append("\r\n</tr>"); #if NO if (newline.Type == ChangeType.Unchanged) { } else if (newline.Type == ChangeType.Inserted) { } else if (newline.Type == ChangeType.Modified) { } else if (oldline.Type == ChangeType.Deleted) { } #endif } #if NO if (string.IsNullOrEmpty(strOldFragmentXml) == false || string.IsNullOrEmpty(strNewFragmentXml) == false) { var xml_differ = new Differ(); var xml_builder = new SideBySideDiffBuilder(xml_differ); var xml_diff_result = xml_builder.BuildDiffModel(GetComparableXmlString(strOldFragmentXml), GetComparableXmlString(strNewFragmentXml)); Debug.Assert(xml_diff_result.OldText.Lines.Count == xml_diff_result.NewText.Lines.Count, ""); for (int index = 0; index < xml_diff_result.NewText.Lines.Count; index++) { var newline = xml_diff_result.NewText.Lines[index]; var oldline = xml_diff_result.OldText.Lines[index]; string strLineClass = "datafield"; if (newline.Type == ChangeType.Modified) { } strResult.Append("\r\n<tr class='" + strLineClass + "'>"); // 创建一个 XML 字段的 HTML 局部 三个 <td> strResult.Append(BuildFragmentFieldHtml(oldline.Type, oldline.Text)); strResult.Append(SEP); strResult.Append(BuildFragmentFieldHtml(newline.Type, newline.Text)); strResult.Append("\r\n</tr>"); } } #endif if (string.IsNullOrEmpty(strOldFragmentXml) == false || string.IsNullOrEmpty(strNewFragmentXml) == false) { string strLineClass = "sepline"; strResult.Append("\r\n<tr class='" + strLineClass + "'>"); strResult.Append("<td class='sepline' colspan='3'> </td>"); strResult.Append("<td class='cross'> </td>"); strResult.Append("<td class='sepline' colspan='3'> </td>"); strResult.Append("\r\n</tr>"); } strResult.Append(DiffXml( 0, strOldFragmentXml, XmlNodeType.Element, strNewFragmentXml, XmlNodeType.Element)); strResult.Append("</table>"); strHtml = strResult.ToString(); return 0; }