// 进行查重 // parameters: // sessioninfo 仅仅用来存放DupResultSet,不应该用来sessioninfo.GetChannel(),而要用channel来进行检索操作 // channel // strOriginBiblioRecPath 发起的书目记录路径 // strOriginBiblioRecXml 发起的书目记录XML // strProjectName 查重方案名 // strStyle includeoriginrecord输出结果中包含发起记录(缺省为不包含) // return: // -1 error // 0 not found // 其他 命中记录条数 public LibraryServerResult SearchDup( SessionInfo sessioninfo1, RmsChannel channel, string strOriginBiblioRecPath, string strOriginBiblioRecXml, string strProjectName, string strStyle, out string strUsedProjectName) { string strError = ""; int nRet = 0; strUsedProjectName = ""; string strDebugInfo = ""; strStyle = strStyle.ToLower(); bool bIncludeOriginRecord = StringUtil.IsInList("includeoriginrecord", strStyle); LibraryServerResult result = new LibraryServerResult(); // 如果没有给出方案名,则需要在<default>元素中找到一个书目库的缺省查重方案 if (String.IsNullOrEmpty(strProjectName) == true) { if (String.IsNullOrEmpty(strOriginBiblioRecPath) == true) { strError = "既没有给出查重方案名,也没有给出记录路径,无法进行查重"; goto ERROR1; } string strOriginBiblioDbName = ResPath.GetDbName(strOriginBiblioRecPath); XmlNode nodeDefault = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//dup/default[@origin='" + strOriginBiblioDbName + "']"); if (nodeDefault == null) { strError = "在没有明确指定查重方案名的情况下,本希望通过相关书目库的缺省查重方案名进行查重。但目前系统没有为书目库 '" + strOriginBiblioDbName + "' 定义缺省查重方案名,无法进行查重"; goto ERROR1; } string strDefaultProjectName = DomUtil.GetAttr(nodeDefault, "project"); if (String.IsNullOrEmpty(strDefaultProjectName) == true) { strError = "书目库 '" + strOriginBiblioDbName + "' 的<default>元素中未定义project属性值"; goto ERROR1; } strProjectName = strDefaultProjectName; } strUsedProjectName = strProjectName; // 获得查重方案定义节点 // return: // -1 出错 // 0 not found // 1 found nRet = GetDupProjectNode(strProjectName, out XmlNode nodeProject, out strError); if (nRet == 0 || nRet == -1) { goto ERROR1; } Debug.Assert(nodeProject != null, ""); DupResultSet alldatabase_set = null; // 所有库的结果集 XmlNodeList nodeDatabases = nodeProject.SelectNodes("database"); // 循环,针对每个数据库进行检索 for (int i = 0; i < nodeDatabases.Count; i++) { XmlNode nodeDatabase = nodeDatabases[i]; string strDatabaseName = DomUtil.GetAttr(nodeDatabase, "name"); string strThreshold = DomUtil.GetAttr(nodeDatabase, "threshold"); int nThreshold = 0; try { nThreshold = Convert.ToInt32(strThreshold); } catch { } List <AccessKeyInfo> aKeyLine = null; // 模拟创建检索点,以获得检索点列表 // return: // -1 error // 0 succeed nRet = GetKeys( // sessioninfo.Channels, channel, strOriginBiblioRecPath, strOriginBiblioRecXml, out aKeyLine, out strError); if (nRet == -1) { goto ERROR1; } DupResultSet onedatabase_set = null; // 一个库的结果集 try { XmlNodeList accesspoints = nodeDatabase.SelectNodes("accessPoint"); // <accessPoint>循环 for (int j = 0; j < accesspoints.Count; j++) { XmlNode accesspoint = accesspoints[j]; string strFrom = DomUtil.GetAttr(accesspoint, "name"); // 获得from所对应的key List <string> keys = GetKeyByFrom(aKeyLine, strFrom); if (keys.Count == 0) { continue; } string strWeight = DomUtil.GetAttr(accesspoint, "weight"); string strSearchStyle = DomUtil.GetAttr(accesspoint, "searchStyle"); int nWeight = 0; try { nWeight = Convert.ToInt32(strWeight); } catch { // 警告定义问题? } for (int k = 0; k < keys.Count; k++) { string strKey = (string)keys[k]; if (strKey == "") { continue; } DupResultSet dupset = null; try { // 针对一个from进行检索 // return: // -1 error // 0 not found // 1 found nRet = SearchOneFrom( // sessioninfo.Channels, channel, strDatabaseName, strFrom, strKey, strSearchStyle, nWeight, nThreshold, 5000, // ??? (bIncludeOriginRecord == false) ? strOriginBiblioRecPath : null, out dupset, out strError); if (nRet == -1) { // ??? 警告检索错误? continue; } if (onedatabase_set == null) { onedatabase_set = dupset; dupset = null; // 避免出 try 范围时被释放。因为内容已经转移给 onedatabase_set 了 continue; } if (nRet == 0) { continue; } Debug.Assert(dupset != null, ""); if (onedatabase_set.Sorted == true) { onedatabase_set.EnsureCreateIndex(getTempFileName); } else { onedatabase_set.Sort(getTempFileName); } // dupset.EnsureCreateIndex(getTempFileName); // 2017/4/14 dupset.Sort(getTempFileName); // Sort() 里面自动确保了创建 Index // 将dupset和前一个set归并 // 归并可以参考ResultSet中的Merge算法 DupResultSet tempset = new DupResultSet(); tempset.Open(false, getTempFileName); // 功能: 合并两个数组 // parameters: // strStyle 运算风格 OR , AND , SUB // sourceLeft 源左边结果集 // sourceRight 源右边结果集 // targetLeft 目标左边结果集 // targetMiddle 目标中间结果集 // targetRight 目标右边结果集 // bOutputDebugInfo 是否输出处理信息 // strDebugInfo 处理信息 // return // -1 出错 // 0 成功 nRet = DupResultSet.Merge("OR", onedatabase_set, dupset, null, // targetLeft, tempset, null, // targetRight, false, out strDebugInfo, out strError); if (nRet == -1) { goto ERROR1; } { if (onedatabase_set != null) { onedatabase_set.Dispose(); } onedatabase_set = tempset; onedatabase_set.Sorted = true; // 归并后产生的结果集自然是符合顺序的 } } finally { if (dupset != null) { dupset.Dispose(); } } } // end of k loop } // end of j loop if (alldatabase_set == null) { alldatabase_set = onedatabase_set; onedatabase_set = null; // 避免出 try 范围时被释放。因为内容已经转移给 alldatabase_set 了 continue; } // 合并 if (onedatabase_set != null) { DupResultSet tempset0 = new DupResultSet(); tempset0.Open(false, getTempFileName); if (alldatabase_set.Sorted == true) { alldatabase_set.EnsureCreateIndex(getTempFileName); } else { alldatabase_set.Sort(getTempFileName); } // onedatabase_set.EnsureCreateIndex(getTempFileName); // 2017/4/14 onedatabase_set.Sort(getTempFileName); // Sort() 里面自动确保了创建 Index nRet = DupResultSet.Merge("OR", alldatabase_set, onedatabase_set, null, // targetLeft, tempset0, null, // targetRight, false, out strDebugInfo, out strError); if (nRet == -1) { goto ERROR1; } { if (alldatabase_set != null) { alldatabase_set.Dispose(); } alldatabase_set = tempset0; alldatabase_set.Sorted = true; } } } finally { if (onedatabase_set != null) { onedatabase_set.Dispose(); } } } // 最后要按照 Weight和Threshold的差额 对结果集进行排序,便于输出 if (alldatabase_set != null) { alldatabase_set.SortStyle = DupResultSetSortStyle.OverThreshold; alldatabase_set.Sort(getTempFileName); } { if (sessioninfo1.DupResultSet != null) { sessioninfo1.DupResultSet.Dispose(); } sessioninfo1.DupResultSet = alldatabase_set; } if (alldatabase_set != null) { result.Value = alldatabase_set.Count; } else { result.Value = 0; } return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 获得查重检索命中结果 // parameters: // lStart 返回命中结果集起始位置 // lCount 返回命中结果集的记录个数 // strBrowseInfoStyle 所返回的DupSearchResult中包含哪些信息 // "cols" 包含浏览列 // "excludecolsoflowthreshold" 不包含权值低于阈值的行的浏览列。要在同时包含cols时才起作用 // searchresults 包含记录信息的DupSearchResult数组 public LibraryServerResult GetDupSearchResult( SessionInfo sessioninfo, long lStart, long lCount, string strBrowseInfoStyle, out DupSearchResult[] searchresults) { string strError = ""; searchresults = null; int nRet = 0; LibraryServerResult result = new LibraryServerResult(); RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } DupResultSet dupset = sessioninfo.DupResultSet; if (dupset == null) { strError = "查重结果集不存在"; goto ERROR1; } dupset.EnsureCreateIndex(getTempFileName); int nCount = (int)lCount; int nStart = (int)lStart; if (nCount == -1) { nCount = (int)dupset.Count - nStart; if (nCount < 0) { nCount = 0; } } else { if (nCount > (int)dupset.Count - nStart) { nCount = (int)dupset.Count - nStart; if (nCount < 0) { nCount = 0; } } } bool bDetail = (StringUtil.IsInList("detail", strBrowseInfoStyle)); bool bExcludeCols = (StringUtil.IsInList("excludecolsoflowthreshold", strBrowseInfoStyle) == true); bool bCols = (StringUtil.IsInList("cols", strBrowseInfoStyle) == true); List <string> pathlist = new List <string>(); List <DupSearchResult> results = new List <DupSearchResult>(); for (int i = 0; i < nCount; i++) // BUG nStart + { DupLineItem item = (DupLineItem)dupset[nStart + i]; // changed DupSearchResult result_item = new DupSearchResult(); results.Add(result_item); result_item.Path = item.Path; result_item.Weight = item.Weight; result_item.Threshold = item.Threshold; if (bDetail) { result_item.Detail = item.Detail; } // paths[i] = item.Path; if (bCols == true) { if (bExcludeCols == true && item.Weight < item.Threshold) { } else { pathlist.Add(item.Path); } } } if (pathlist.Count > 0) { // string[] paths = new string[pathlist.Count]; string[] paths = StringUtil.FromListString(pathlist); nRet = channel.GetBrowseRecords(paths, "cols", out ArrayList aRecord, out strError); if (nRet == -1) { strError = "GetBrowseRecords() error: " + strError; goto ERROR1; } int j = 0; for (int i = 0; i < results.Count; i++) { DupSearchResult result_item = results[i]; if (result_item.Path != pathlist[j]) { continue; } string[] cols = (string[])aRecord[j]; results[i].Cols = cols; // style中不包含id j++; if (j >= pathlist.Count) { break; } } } searchresults = new DupSearchResult[results.Count]; results.CopyTo(searchresults); result.Value = searchresults.Length; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 获得实用库信息 public LibraryServerResult GetUtilInfo( SessionInfo sessioninfo, string strAction, string strDbName, string strFrom, string strKey, string strValueAttrName, out string strValue) { string strError = ""; strValue = ""; int nRet = 0; LibraryServerResult result = new LibraryServerResult(); /* * if (String.IsNullOrEmpty(strKeyAttrName) == true) * strKeyAttrName = "k"; * */ if (String.IsNullOrEmpty(strValueAttrName) == true) { strValueAttrName = "v"; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } string strPath = ""; string strXml = ""; byte[] timestamp = null; // 检索实用库记录的路径和记录体 // return: // -1 error(注:检索命中多条情况被当作错误返回) // 0 not found // 1 found nRet = SearchUtilPathAndRecord( // sessioninfo.Channels, channel, strDbName, strKey, strFrom, out strPath, out strXml, out timestamp, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { result.ErrorCode = ErrorCode.NotFound; result.ErrorInfo = "库名为 '" + strDbName + "' 途径为 '" + strFrom + "' 键值为 '" + strKey + "' 的记录没有找到"; result.Value = 0; return(result); } // 如果动作为获得整个记录 if (strAction == "getrecord") { strValue = strXml; result.Value = 1; return(result); } XmlDocument domRecord = new XmlDocument(); try { domRecord.LoadXml(strXml); } catch (Exception ex) { strError = "装载路径为'" + strPath + "'的xml记录时出错: " + ex.Message; goto ERROR1; } strValue = DomUtil.GetAttr(domRecord.DocumentElement, strValueAttrName); result.Value = 1; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 设置实用库信息 // strRootElementName 根元素名。如果为空,系统自会用<r>作为根元素 // strKeyAttrName key属性名。如果为空,系统自动会用k // strValueAttrName value属性名。如果为空,系统自动会用v public LibraryServerResult SetUtilInfo( SessionInfo sessioninfo, string strAction, string strDbName, string strFrom, string strRootElementName, string strKeyAttrName, string strValueAttrName, string strKey, string strValue) { string strError = ""; int nRet = 0; LibraryServerResult result = new LibraryServerResult(); string strPath = ""; string strXml = ""; byte[] timestamp = null; bool bRedo = false; if (String.IsNullOrEmpty(strRootElementName) == true) { strRootElementName = "r"; // 最简单的缺省模式 } if (String.IsNullOrEmpty(strKeyAttrName) == true) { strKeyAttrName = "k"; } if (String.IsNullOrEmpty(strValueAttrName) == true) { strValueAttrName = "v"; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } // 检索实用库记录的路径和记录体 // return: // -1 error(注:检索命中多条情况被当作错误返回) // 0 not found // 1 found nRet = SearchUtilPathAndRecord( // sessioninfo.Channels, channel, strDbName, strKey, strFrom, out strPath, out strXml, out timestamp, out strError); if (nRet == -1) { goto ERROR1; } // 如果动作为直接设置整个记录 if (strAction == "setrecord") { if (nRet == 0) { strPath = strDbName + "/?"; } strXml = strValue; } else { // 根据若干信息构造出记录 if (nRet == 0) { strPath = strDbName + "/?"; // strXml = "<" + strRootElementName + " " + strKeyAttrName + "='" + strKey + "' " + strValueAttrName + "='" + strValue + "'/>"; // 2011/12/11 XmlDocument dom = new XmlDocument(); dom.LoadXml("<" + strRootElementName + "/>"); DomUtil.SetAttr(dom.DocumentElement, strKeyAttrName, strKey); DomUtil.SetAttr(dom.DocumentElement, strValueAttrName, strValue); strXml = dom.DocumentElement.OuterXml; } else { string strPartXml = "/xpath/<locate>@" + strValueAttrName + "</locate><create>@" + strValueAttrName + "</create>"; strPath += strPartXml; strXml = strValue; } } #if NO RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } #endif byte[] baOutputTimeStamp = null; string strOutputPath = ""; int nRedoCount = 0; REDO: long lRet = channel.DoSaveTextRes(strPath, strXml, false, // bInlucdePreamble "ignorechecktimestamp", // style timestamp, out baOutputTimeStamp, out strOutputPath, out strError); if (lRet == -1) { if (bRedo == true) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch && nRedoCount < 10) { timestamp = baOutputTimeStamp; nRedoCount++; goto REDO; } } goto ERROR1; } result.Value = 1; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// (根据一定排架体系)检索出某一类的同类书的索取号 // parameters: // strArrangeGroupName 排架体系名。如果为"!xxx"形式,表示通过馆藏地点名来暗示排架体系名 public LibraryServerResult SearchOneClassCallNumber( SessionInfo sessioninfo, string strArrangeGroupName, string strClass, string strResultSetName, out string strQueryXml) { strQueryXml = ""; string strError = ""; LibraryServerResult result = new LibraryServerResult(); if (String.IsNullOrEmpty(strArrangeGroupName) == true) { strError = "strArrangeGroupName参数值不能为空"; goto ERROR1; } if (strArrangeGroupName[0] == '!') { string strTemp = GetArrangeGroupName(strArrangeGroupName.Substring(1)); if (strTemp == null) { strError = "馆藏地点名 " + strArrangeGroupName.Substring(1) + " 没有找到对应的排架体系名"; goto ERROR1; } strArrangeGroupName = strTemp; } // <location>元素数组 XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("//callNumber/group[@name='" + strArrangeGroupName + "']/location"); if (nodes.Count == 0) { strError = "library.xml中尚未配置有关 '" + strArrangeGroupName + "' 的<callNumber>/<group>/<location>相关参数"; goto ERROR1; } string strTargetList = ""; // 遍历所有实体库 for (int i = 0; i < this.ItemDbs.Count; i++) { string strItemDbName = this.ItemDbs[i].DbName; if (String.IsNullOrEmpty(strItemDbName) == true) { continue; } if (String.IsNullOrEmpty(strTargetList) == false) { strTargetList += ";"; } strTargetList += strItemDbName + ":索取类号"; } int nCount = 0; // 构造检索式 for (int i = 0; i < nodes.Count; i++) { XmlNode node = nodes[i]; string strLocationName = DomUtil.GetAttr(node, "name"); if (String.IsNullOrEmpty(strLocationName) == true) { continue; } if (nCount > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strLocationName = strLocationName.Replace("*", "%"); /* * strQueryXml += "<item><word>" + StringUtil.GetXmlStringSimple(strLocationName + "|" + strClass) + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang>"; * */ strQueryXml += "<item><word>" + StringUtil.GetXmlStringSimple(strLocationName + "|" + strClass + "/") + "</word><match>left</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang>"; nCount++; } strQueryXml = "<target list='" + StringUtil.GetXmlStringSimple(strTargetList) // 2007/9/14 + "'>" + strQueryXml + "</target>"; RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } long lRet = channel.DoSearch(strQueryXml, strResultSetName, // "default", "keyid", // "", // strOuputStyle out strError); if (lRet == -1) { goto ERROR1; } if (lRet == 0) { result.Value = 0; result.ErrorInfo = "not found"; result.ErrorCode = ErrorCode.NotFound; return(result); } result.Value = lRet; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 将刚从dt1000升级上来的读者和实体记录进行交叉处理 // parameters: // nStart 从第几个借阅的册事项开始处理 // nCount 共处理几个借阅的册事项 // nProcessedBorrowItems [out]本次处理了多少个借阅册事项 // nTotalBorrowItems [out]当前读者一共包含有多少个借阅册事项 // result.Value // -1 错误。 // 0 成功。 // 1 有警告 public LibraryServerResult CrossRefBorrowInfo( // RmsChannelCollection Channels, RmsChannel channel, string strReaderBarcode, int nStart, int nCount, out int nProcessedBorrowItems, out int nTotalBorrowItems) { string strError = ""; nTotalBorrowItems = 0; nProcessedBorrowItems = 0; int nRet = 0; string strWarning = ""; int nRedoCount = 0; // string strCheckError = ""; LibraryServerResult result = new LibraryServerResult(); // int nErrorCount = 0; REDO_CHANGE_READERREC: // 加读者记录锁 #if DEBUG_LOCK_READER this.WriteErrorLog("CrossRefBorrowInfo 开始为读者加写锁 '" + strReaderBarcode + "'"); #endif this.ReaderLocks.LockForWrite(strReaderBarcode); try // 读者记录锁定范围开始 { // 读入读者记录 string strReaderXml = ""; string strOutputReaderRecPath = ""; byte[] reader_timestamp = null; nRet = this.GetReaderRecXml( // Channels, channel, strReaderBarcode, out strReaderXml, out strOutputReaderRecPath, out reader_timestamp, out strError); if (nRet == 0) { result.Value = -1; result.ErrorInfo = "读者证条码号 '" + strReaderBarcode + "' 不存在"; result.ErrorCode = ErrorCode.ReaderBarcodeNotFound; return(result); } if (nRet == -1) { strError = "读入读者记录时发生错误: " + strError; goto ERROR1; } XmlDocument readerdom = null; nRet = LibraryApplication.LoadToDom(strReaderXml, out readerdom, out strError); if (nRet == -1) { strError = "装载读者记录进入XML DOM时发生错误: " + strError; goto ERROR1; } bool bReaderRecChanged = false; // 修改读者记录中overdues/overdue中的价格单位,并加入id // return: // -1 error // 0 not changed // 1 changed nRet = ModifyReaderRecord( ref readerdom, out strWarning, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 1) { bReaderRecChanged = true; } // TODO: strWarning内容如何处理? XmlNodeList nodesBorrow = readerdom.DocumentElement.SelectNodes("borrows/borrow"); nTotalBorrowItems = nodesBorrow.Count; if (nTotalBorrowItems == 0) { result.Value = 0; result.ErrorInfo = "读者记录中没有借还信息。"; return(result); } if (nStart >= nTotalBorrowItems) { strError = "nStart参数值" + nStart.ToString() + "大于当前读者记录中的借阅册个数" + nTotalBorrowItems.ToString(); goto ERROR1; } nProcessedBorrowItems = 0; for (int i = nStart; i < nTotalBorrowItems; i++) { if (nCount != -1 && nProcessedBorrowItems >= nCount) { break; } // 一个API最多做10条 if (nProcessedBorrowItems >= 10) { break; } XmlNode nodeBorrow = nodesBorrow[i]; string strItemBarcode = DomUtil.GetAttr(nodeBorrow, "barcode"); nProcessedBorrowItems++; if (String.IsNullOrEmpty(strItemBarcode) == true) { strWarning += "读者记录中<borrow>元素barcode属性值不能为空; "; continue; } string strBorrowDate = DomUtil.GetAttr(nodeBorrow, "borrowDate"); string strBorrowPeriod = DomUtil.GetAttr(nodeBorrow, "borrowPeriod"); if (String.IsNullOrEmpty(strBorrowDate) == true) { strWarning += "读者记录中<borrow>元素borrowDate属性不能为空; "; continue; } if (String.IsNullOrEmpty(strBorrowPeriod) == true) { strWarning += "读者记录中<borrow>元素borrowPeriod属性不能为空; "; continue; } // 把实体记录借阅信息详细化 // return: // 0 册条码号没有找到对应的册记录 // 1 成功 nRet = ModifyEntityRecord( // Channels, channel, null, // strEntityRecPath strItemBarcode, strReaderBarcode, strBorrowDate, strBorrowPeriod, out strError); if (nRet == -1) { strWarning += "ModifyEntityRecord() [strItemBarcode='" + strItemBarcode + "' strReaderBarcode='" + strReaderBarcode + "'] error : " + strError + "; "; continue; } // 2008/10/7 if (nRet == 0) { strWarning += "册条码号 '" + strItemBarcode + "' 对应的记录不存在; "; continue; } } if (bReaderRecChanged == true) { byte[] output_timestamp = null; string strOutputPath = ""; #if NO RmsChannel channel = Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } #endif // 写回读者记录 long lRet = channel.DoSaveTextRes(strOutputReaderRecPath, readerdom.OuterXml, false, "content", // ,ignorechecktimestamp reader_timestamp, out output_timestamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { nRedoCount++; if (nRedoCount > 10) { strError = "写回读者记录的时候,遇到时间戳冲突,并因此重试10次,仍失败..."; goto ERROR1; } goto REDO_CHANGE_READERREC; } goto ERROR1; } // 及时更新时间戳 reader_timestamp = output_timestamp; } } finally { this.ReaderLocks.UnlockForWrite(strReaderBarcode); #if DEBUG_LOCK_READER this.WriteErrorLog("CrossRefBorrowInfo 结束为读者加写锁 '" + strReaderBarcode + "'"); #endif } if (String.IsNullOrEmpty(strWarning) == false) { result.Value = 1; result.ErrorInfo = strWarning; } else { result.Value = 0; } return(result); ERROR1: result.Value = -1; result.ErrorInfo = strError; result.ErrorCode = ErrorCode.SystemError; return(result); }
// 获得种次号尾号 public LibraryServerResult GetOneClassTailNumber( SessionInfo sessioninfo, string strArrangeGroupName, string strClass, out string strTailNumber) { strTailNumber = ""; string strError = ""; LibraryServerResult result = new LibraryServerResult(); if (String.IsNullOrEmpty(strArrangeGroupName) == true) { strError = "strArrangeGroupName参数值不能为空"; goto ERROR1; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } string strPath = ""; string strXml = ""; byte[] timestamp = null; // 检索尾号记录的路径和记录体 // return: // -1 error // 0 not found // 1 found int nRet = SearchOneClassTailNumberPathAndRecord( // sessioninfo.Channels, channel, strArrangeGroupName, strClass, out strPath, out strXml, out timestamp, out strError); if (nRet == -1) { goto ERROR1; } if (nRet == 0) { result.ErrorCode = ErrorCode.NotFound; result.ErrorInfo = strError; result.Value = 0; return(result); } XmlDocument dom = new XmlDocument(); try { dom.LoadXml(strXml); } catch (Exception ex) { strError = "尾号记录 '" + strPath + "' XML装入DOM时发生错误: " + ex.Message; goto ERROR1; } strTailNumber = DomUtil.GetAttr(dom.DocumentElement, "v"); result.Value = 1; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 设置种次号尾号 public LibraryServerResult SetOneClassTailNumber( SessionInfo sessioninfo, string strAction, string strArrangeGroupName, string strClass, string strTestNumber, out string strOutputNumber) { strOutputNumber = ""; string strError = ""; LibraryServerResult result = new LibraryServerResult(); RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } string strPath = ""; string strXml = ""; byte[] timestamp = null; // 检索尾号记录的路径和记录体 // return: // -1 error // 0 not found // 1 found int nRet = SearchOneClassTailNumberPathAndRecord( // sessioninfo.Channels, channel, strArrangeGroupName, strClass, out strPath, out strXml, out timestamp, out strError); if (nRet == -1) { goto ERROR1; } string strZhongcihaoDbName = GetTailDbName(strArrangeGroupName); if (String.IsNullOrEmpty(strZhongcihaoDbName) == true) { // TODO: 这里报错还需要精确一些,对于带有'!'的馆藏地点名 strError = "无法通过排架体系名 '" + strArrangeGroupName + "' 获得种次号库名"; goto ERROR1; } // byte[] baOutputTimestamp = null; bool bNewRecord = false; long lRet = 0; #if NO RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } #endif byte[] output_timestamp = null; string strOutputPath = ""; if (strAction == "conditionalpush") { if (nRet == 0) { // 新创建记录 strPath = strZhongcihaoDbName + "/?"; strXml = "<r c='" + strClass + "' v='" + strTestNumber + "'/>"; bNewRecord = true; } else { string strPartXml = "/xpath/<locate>@v</locate><action>Push</action>"; strPath += strPartXml; strXml = strTestNumber; bNewRecord = false; } lRet = channel.DoSaveTextRes(strPath, strXml, false, "content", timestamp, // timestamp, out output_timestamp, out strOutputPath, out strError); if (lRet == -1) { strError = "保存尾号记录时出错: " + strError; goto ERROR1; } if (bNewRecord == true) { strOutputNumber = strTestNumber; } else { strOutputNumber = strError; } goto END1; } else if (strAction == "increase") { string strDefaultNumber = strTestNumber; if (nRet == 0) { // 新创建记录 strPath = strZhongcihaoDbName + "/?"; strXml = "<r c='" + strClass + "' v='" + strDefaultNumber + "'/>"; bNewRecord = true; } else { string strPartXml = "/xpath/<locate>@v</locate><action>+AddInteger</action>"; strPath += strPartXml; strXml = "1"; bNewRecord = false; } // lRet = channel.DoSaveTextRes(strPath, strXml, false, "content", timestamp, // timestamp, out output_timestamp, out strOutputPath, out strError); if (lRet == -1) { strError = "保存尾号记录时出错: " + strError; goto ERROR1; } if (bNewRecord == true) { strOutputNumber = strDefaultNumber; } else { strOutputNumber = strError; } goto END1; } else if (strAction == "save") { string strTailNumber = strTestNumber; if (nRet == 0) { strPath = strZhongcihaoDbName + "/?"; } else { // 覆盖记录 if (String.IsNullOrEmpty(strPath) == true) { strError = "记录存在时strPath居然为空"; goto ERROR1; } } strXml = "<r c='" + strClass + "' v='" + strTailNumber + "'/>"; lRet = channel.DoSaveTextRes(strPath, strXml, false, "content", timestamp, // timestamp, out output_timestamp, out strOutputPath, out strError); if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { strError = "尾号记录时间戳不匹配,说明可能被他人修改过。详细原因: " + strError; goto ERROR1; } strError = "保存尾号记录时出错: " + strError; goto ERROR1; } } else { strError = "无法识别的strAction参数值 '" + strAction + "'"; goto ERROR1; } END1: result.Value = 1; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// 检索同类记录 public LibraryServerResult SearchUsedZhongcihao( SessionInfo sessioninfo, string strZhongcihaoGroupName, string strClass, string strResultSetName, out string strQueryXml) { strQueryXml = ""; string strError = ""; LibraryServerResult result = new LibraryServerResult(); if (String.IsNullOrEmpty(strZhongcihaoGroupName) == true) { strError = "strZhongcihaoGroupName参数值不能为空"; goto ERROR1; } if (strZhongcihaoGroupName[0] == '!') { string strTemp = GetZhongcihaoGroupName(strZhongcihaoGroupName.Substring(1)); if (strTemp == null) { strError = "书目库名 " + strZhongcihaoGroupName.Substring(1) + " 没有找到对应的种次号组名"; goto ERROR1; } strZhongcihaoGroupName = strTemp; } XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("//zhongcihao/group[@name='" + strZhongcihaoGroupName + "']/database"); if (nodes.Count == 0) { strError = "library.xml中尚未配置有关 '" + strZhongcihaoGroupName + "'的<zhongcihao>/<group>/<database>相关参数"; goto ERROR1; } // 构造检索式 for (int i = 0; i < nodes.Count; i++) { XmlNode node = nodes[i]; string strDbName = DomUtil.GetAttr(node, "name"); if (string.IsNullOrEmpty(strDbName) == true) { strError = "<database>元素必须有非空的name属性值"; goto ERROR1; } Debug.Assert(String.IsNullOrEmpty(strDbName) == false, ""); if (i > 0) { Debug.Assert(String.IsNullOrEmpty(strQueryXml) == false, ""); strQueryXml += "<operator value='OR'/>"; } strQueryXml += "<target list='" + StringUtil.GetXmlStringSimple(strDbName + ":" + "索取号") // 2007/9/14 + "'><item><word>" + StringUtil.GetXmlStringSimple(strClass) + "/" + "</word><match>left</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>"; } if (nodes.Count > 0) { strQueryXml = "<group>" + strQueryXml + "</group>"; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { strError = "get channel error"; goto ERROR1; } long lRet = channel.DoSearch(strQueryXml, strResultSetName, // "default", "keyid", // strOuputStyle out strError); if (lRet == -1) { goto ERROR1; } if (lRet == 0) { result.Value = 0; result.ErrorInfo = "not found"; result.ErrorCode = ErrorCode.NotFound; return(result); } result.Value = lRet; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
// parameters: // strBrowseInfoStyle 返回的特性。cols 返回实体记录的浏览列 public LibraryServerResult GetCallNumberSearchResult( SessionInfo sessioninfo, string strArrangeGroupName, string strResultSetName, long lStart, long lCount, string strBrowseInfoStyle, string strLang, out CallNumberSearchResult[] searchresults) { string strError = ""; searchresults = null; LibraryServerResult result = new LibraryServerResult(); // int nRet = 0; long lRet = 0; if (String.IsNullOrEmpty(strArrangeGroupName) == true) { strError = "strArrangeGroupName参数值不能为空"; goto ERROR1; } if (strArrangeGroupName[0] == '!') { string strTemp = GetArrangeGroupName(strArrangeGroupName.Substring(1)); if (strTemp == null) { strError = "馆藏地点名 " + strArrangeGroupName.Substring(1) + " 没有找到对应的排架体系名"; goto ERROR1; } strArrangeGroupName = strTemp; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { result.Value = -1; result.ErrorInfo = "get channel error"; result.ErrorCode = ErrorCode.SystemError; return(result); } if (String.IsNullOrEmpty(strResultSetName) == true) { strResultSetName = "default"; } bool bCols = StringUtil.IsInList("cols", strBrowseInfoStyle); string strBrowseStyle = "keyid,id,key"; if (bCols == true) { strBrowseStyle += ",cols,format:cfgs/browse_callnumber"; } Record[] origin_searchresults = null; // lRet = channel.DoGetSearchResult( strResultSetName, lStart, lCount, strBrowseStyle, // "id", strLang, null, out origin_searchresults, out strError); if (lRet == -1) { goto ERROR1; } long lResultCount = lRet; searchresults = new CallNumberSearchResult[origin_searchresults.Length]; for (int i = 0; i < origin_searchresults.Length; i++) { CallNumberSearchResult item = new CallNumberSearchResult(); Record record = origin_searchresults[i]; item.ItemRecPath = record.Path; searchresults[i] = item; string strLocation = ""; item.CallNumber = BuildAccessNoKeyString(record.Keys, out strLocation); if (bCols == true && record.Cols != null) { if (record.Cols.Length > 0) { item.ParentID = record.Cols[0]; } if (record.Cols.Length > 1) { item.Location = record.Cols[1]; } if (record.Cols.Length > 2) { item.Barcode = record.Cols[2]; } } if (string.IsNullOrEmpty(item.Location) == true) { item.Location = strLocation; // 用从keys中得来的代替。可能有大小写的差异 --- keys中都是大写 } #if NO if (bCols == true) { // 继续填充其余成员 string strXml = ""; string strMetaData = ""; byte[] timestamp = null; string strOutputPath = ""; lRet = channel.GetRes(item.ItemRecPath, out strXml, out strMetaData, out timestamp, out strOutputPath, out strError); if (lRet == -1) { item.ErrorInfo = "获取记录 '" + item.ItemRecPath + "' 出错: " + strError; continue; } XmlDocument dom = new XmlDocument(); try { dom.LoadXml(strXml); } catch (Exception ex) { item.ErrorInfo = "记录 '" + item.ItemRecPath + "' XML装载到DOM时出错: " + ex.Message; continue; } /* * item.CallNumber = DomUtil.GetElementText(dom.DocumentElement, * "accessNo"); * */ item.ParentID = DomUtil.GetElementText(dom.DocumentElement, "parent"); item.Location = DomUtil.GetElementText(dom.DocumentElement, "location"); item.Barcode = DomUtil.GetElementText(dom.DocumentElement, "barcode"); } #endif } result.Value = lResultCount; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
public LibraryServerResult GetZhongcihaoSearchResult( SessionInfo sessioninfo, string strZhongcihaoGroupName, string strResultSetName, long lStart, long lCount, string strBrowseInfoStyle, string strLang, out ZhongcihaoSearchResult[] searchresults) { string strError = ""; searchresults = null; LibraryServerResult result = new LibraryServerResult(); int nRet = 0; long lRet = 0; if (String.IsNullOrEmpty(strZhongcihaoGroupName) == true) { strError = "strZhongcihaoGroupName参数值不能为空"; goto ERROR1; } if (strZhongcihaoGroupName[0] == '!') { string strTemp = GetZhongcihaoGroupName(strZhongcihaoGroupName.Substring(1)); if (strTemp == null) { strError = "书目库名 " + strZhongcihaoGroupName.Substring(1) + " 没有找到对应的种次号组名"; goto ERROR1; } strZhongcihaoGroupName = strTemp; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { result.Value = -1; result.ErrorInfo = "get channel error"; result.ErrorCode = ErrorCode.SystemError; return(result); } // XmlNode nodeNsTable = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//zhongcihao/nstable"); XmlNamespaceManager mngr = null; if (nodeNsTable != null) { // 准备名字空间环境 nRet = PrepareNs( nodeNsTable, out mngr, out strError); if (nRet == -1) { goto ERROR1; } } // 构造数据库定义和库名的对照表 XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("//zhongcihao/group[@name='" + strZhongcihaoGroupName + "']/database"); if (nodes.Count == 0) { strError = "library.xml中尚未配置有关 '" + strZhongcihaoGroupName + "'的<zhongcihao>/<group>/<database>相关参数"; goto ERROR1; } Hashtable db_prop_table = new Hashtable(); for (int i = 0; i < nodes.Count; i++) { XmlNode node = nodes[i]; DbZhongcihaoProperty prop = new DbZhongcihaoProperty(); prop.DbName = DomUtil.GetAttr(node, "name"); prop.NumberXPath = DomUtil.GetAttr(node, "rightxpath"); prop.TitleXPath = DomUtil.GetAttr(node, "titlexpath"); prop.AuthorXPath = DomUtil.GetAttr(node, "authorxpath"); db_prop_table[prop.DbName] = prop; } if (String.IsNullOrEmpty(strResultSetName) == true) { strResultSetName = "default"; } Record[] origin_searchresults = null; // lRet = channel.DoGetSearchResult( strResultSetName, lStart, lCount, "id", strLang, null, out origin_searchresults, out strError); if (lRet == -1) { goto ERROR1; } long lResultCount = lRet; searchresults = new ZhongcihaoSearchResult[origin_searchresults.Length]; for (int i = 0; i < origin_searchresults.Length; i++) { ZhongcihaoSearchResult item = new ZhongcihaoSearchResult(); item.Path = origin_searchresults[i].Path; searchresults[i] = item; // 继续填充其余成员 string strXml = ""; string strMetaData = ""; byte[] timestamp = null; string strOutputPath = ""; lRet = channel.GetRes(item.Path, out strXml, out strMetaData, out timestamp, out strOutputPath, out strError); if (lRet == -1) { item.Zhongcihao = "获取记录 '" + item.Path + "' 出错: " + strError; continue; } string strDbName = ResPath.GetDbName(item.Path); DbZhongcihaoProperty prop = (DbZhongcihaoProperty)db_prop_table[strDbName]; if (prop == null) { item.Zhongcihao = "数据库名 '" + strDbName + "' 不在定义的种次号特性(<zhongcihao>/<group>/<database>)中"; continue; } string strNumber = ""; string strTitle = ""; string strAuthor = ""; nRet = GetRecordProperties( strXml, prop, mngr, out strNumber, out strTitle, out strAuthor, out strError); if (nRet == -1) { item.Zhongcihao = strError; continue; } item.Zhongcihao = strNumber; item.Cols = new string[2]; item.Cols[0] = strTitle; item.Cols[1] = strAuthor; } result.Value = lResultCount; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
public LibraryServerResult GetZhongcihaoSearchResult( SessionInfo sessioninfo, string strZhongcihaoGroupName, string strResultSetName, long lStart, long lCount, string strBrowseInfoStyle, string strLang, out ZhongcihaoSearchResult[] searchresults) { string strError = ""; searchresults = null; LibraryServerResult result = new LibraryServerResult(); // int nRet = 0; long lRet = 0; if (String.IsNullOrEmpty(strZhongcihaoGroupName) == true) { strError = "strZhongcihaoGroupName参数值不能为空"; goto ERROR1; } if (strZhongcihaoGroupName[0] == '!') { string strTemp = GetZhongcihaoGroupName(strZhongcihaoGroupName.Substring(1)); if (strTemp == null) { strError = "书目库名 " + strZhongcihaoGroupName.Substring(1) + " 没有找到对应的种次号组名"; goto ERROR1; } strZhongcihaoGroupName = strTemp; } RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl); if (channel == null) { result.Value = -1; result.ErrorInfo = "get channel error"; result.ErrorCode = ErrorCode.SystemError; return(result); } /* * * // * XmlNode nodeNsTable = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//zhongcihao/nstable"); * * XmlNamespaceManager mngr = null; * * if (nodeNsTable != null) * { * // 准备名字空间环境 * nRet = PrepareNs( * nodeNsTable, * out mngr, * out strError); * if (nRet == -1) * goto ERROR1; * } * * // 构造数据库定义和库名的对照表 * XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("//zhongcihao/group[@name='" + strZhongcihaoGroupName + "']/database"); * if (nodes.Count == 0) * { * strError = "library.xml中尚未配置有关 '" + strZhongcihaoGroupName + "'的<zhongcihao>/<group>/<database>相关参数"; * goto ERROR1; * } * * Hashtable db_prop_table = new Hashtable(); * * for (int i = 0; i < nodes.Count; i++) * { * XmlNode node = nodes[i]; * * DbZhongcihaoProperty prop = new DbZhongcihaoProperty(); * prop.DbName = DomUtil.GetAttr(node, "name"); * prop.NumberXPath = DomUtil.GetAttr(node, "rightxpath"); * prop.TitleXPath = DomUtil.GetAttr(node, "titlexpath"); * prop.AuthorXPath = DomUtil.GetAttr(node, "authorxpath"); * * db_prop_table[prop.DbName] = prop; * } * */ bool bCols = (StringUtil.IsInList("cols", strBrowseInfoStyle) == true); string strBrowseStyle = "keyid,key,id"; if (bCols == true) { strBrowseStyle += ",cols"; } if (String.IsNullOrEmpty(strResultSetName) == true) { strResultSetName = "default"; } Record[] origin_searchresults = null; // lRet = channel.DoGetSearchResult( strResultSetName, lStart, lCount, strBrowseStyle, // "id", strLang, null, out origin_searchresults, out strError); if (lRet == -1) { goto ERROR1; } long lResultCount = lRet; searchresults = new ZhongcihaoSearchResult[origin_searchresults.Length]; for (int i = 0; i < origin_searchresults.Length; i++) { ZhongcihaoSearchResult item = new ZhongcihaoSearchResult(); Record origin_item = origin_searchresults[i]; item.Path = origin_item.Path; searchresults[i] = item; item.Zhongcihao = BuildZhongcihaoString(origin_item.Keys); item.Cols = origin_item.Cols; } #if NO List <string> pathlist = new List <string>(); searchresults = new ZhongcihaoSearchResult[origin_searchresults.Length]; for (int i = 0; i < origin_searchresults.Length; i++) { ZhongcihaoSearchResult item = new ZhongcihaoSearchResult(); item.Path = origin_searchresults[i].Path; searchresults[i] = item; item.Zhongcihao = BuildZhongcihaoString(origin_searchresults[i].Keys); if (bCols == true) { pathlist.Add(item.Path); } } if (pathlist.Count > 0) { // string[] paths = new string[pathlist.Count]; string[] paths = StringUtil.FromListString(pathlist); ArrayList aRecord = null; nRet = channel.GetBrowseRecords(paths, "cols", out aRecord, out strError); if (nRet == -1) { strError = "GetBrowseRecords() error: " + strError; goto ERROR1; } int j = 0; for (int i = 0; i < searchresults.Length; i++) { ZhongcihaoSearchResult result_item = searchresults[i]; if (result_item.Path != pathlist[j]) { continue; } string[] cols = (string[])aRecord[j]; result_item.Cols = cols; // style中不包含id j++; if (j >= pathlist.Count) { break; } } } #endif result.Value = lResultCount; return(result); ERROR1: result.Value = -1; result.ErrorCode = ErrorCode.SystemError; result.ErrorInfo = strError; return(result); }
void BuildAmerceRecord(XmlDocument domOperLog, out string strBodyXml, out string strReaderBarcode, out string strReaderRefID) { strBodyXml = ""; strReaderBarcode = ""; strReaderRefID = ""; string strError = ""; // string strOperation = DomUtil.GetElementText(domOperLog.DocumentElement, "operation"); string strAction = DomUtil.GetElementText(domOperLog.DocumentElement, "action"); string strLibraryCode = DomUtil.GetElementText(domOperLog.DocumentElement, "libraryCode"); string strReaderRecord = DomUtil.GetElementText(domOperLog.DocumentElement, "readerRecord"); XmlDocument readerdom = new XmlDocument(); readerdom.LoadXml(strReaderRecord); strReaderRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); // 构造内容 XmlDocument bodydom = new XmlDocument(); bodydom.LoadXml("<root />"); if (strAction == "amerce") { DomUtil.SetElementText(bodydom.DocumentElement, "type", "交费"); } else if (strAction == "undo") { DomUtil.SetElementText(bodydom.DocumentElement, "type", "撤销交费"); } else if (strAction == "modifyprice") { // DomUtil.SetElementText(bodydom.DocumentElement, "type", "变更交费金额"); strBodyXml = ""; return; } else if (strAction == "expire") { DomUtil.SetElementText(bodydom.DocumentElement, "type", "以停代金到期"); } else if (strAction == "modifycomment") { // DomUtil.SetElementText(bodydom.DocumentElement, "type", "修改交费注释"); strBodyXml = ""; return; } else { #if NO strError = "无法识别的 strAction '" + strAction + "'"; throw new Exception(strError); #endif strBodyXml = ""; return; } // 复制日志记录中的一级元素 XmlNodeList nodes = domOperLog.DocumentElement.SelectNodes("*"); foreach (XmlNode node in nodes) { if (node.Name == "readerRecord" || node.Name == "oldReaderRecord" || node.Name == "expireOverdues" || node.Name == "amerceItems" || node.Name == "amerceRecord") { continue; } DomUtil.SetElementText(bodydom.DocumentElement, node.Name, node.InnerText); } { XmlElement record = bodydom.CreateElement("patronRecord"); bodydom.DocumentElement.AppendChild(record); record.InnerXml = readerdom.DocumentElement.InnerXml; DomUtil.DeleteElement(record, "borrowHistory"); DomUtil.DeleteElement(record, "password"); DomUtil.DeleteElement(record, "fingerprint"); DomUtil.DeleteElement(record, "face"); DomUtil.SetElementText(record, "libraryCode", strLibraryCode); } // items XmlElement amerce_items = bodydom.DocumentElement.SelectSingleNode("items") as XmlElement; if (amerce_items == null) { amerce_items = bodydom.CreateElement("items"); bodydom.DocumentElement.AppendChild(amerce_items); } XmlNodeList amerce_records = domOperLog.DocumentElement.SelectNodes("amerceRecord"); foreach (XmlElement amerce_record in amerce_records) { string strAmercedXml = amerce_record.InnerText; if (string.IsNullOrEmpty(strAmercedXml)) { continue; } string strOverdueString = ""; string strTemp = ""; int nRet = LibraryApplication.ConvertAmerceRecordToOverdueString(strAmercedXml, out strTemp, out strOverdueString, out strError); if (nRet == -1) { throw new Exception(strError); } XmlDocumentFragment fragment = bodydom.CreateDocumentFragment(); fragment.InnerXml = strOverdueString; amerce_items.AppendChild(fragment); } // expire 情况要把 expireOverdues/overdue 翻译为 items/overdue 元素 if (strAction == "expire") { XmlElement expireOverdues = domOperLog.DocumentElement.SelectSingleNode("expiredOverdues") as XmlElement; if (expireOverdues != null) { amerce_items.InnerXml = expireOverdues.InnerXml; } } else { // 留着 amerceItem 元素做测试对照 } RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); if (channel == null) { strError = "channel == null"; throw new Exception(strError); } // 为 overdue 元素添加 summary 属性 XmlNodeList overdues = bodydom.DocumentElement.SelectNodes("items/overdue"); foreach (XmlElement overdue in overdues) { string strItemBarcode = overdue.GetAttribute("barcode"); if (string.IsNullOrEmpty(strItemBarcode)) { continue; } // 加入书目摘要 string strSummary = ""; string strBiblioRecPath = ""; LibraryServerResult result = this.App.GetBiblioSummary( null, channel, strItemBarcode, "", // strItemRecPath, null, out strBiblioRecPath, out strSummary); if (result.Value == -1) { // strSummary = result.ErrorInfo; } else { overdue.SetAttribute("summary", strSummary); } } strBodyXml = bodydom.DocumentElement.OuterXml; }
void BuildBorrowReturnRecord(XmlDocument domOperLog, out string strBodyXml, out string strReaderBarcode, out string strReaderRefID) { strBodyXml = ""; strReaderBarcode = ""; strReaderRefID = ""; string strError = ""; string strOperation = DomUtil.GetElementText(domOperLog.DocumentElement, "operation"); string strLibraryCode = DomUtil.GetElementText(domOperLog.DocumentElement, "libraryCode"); string strReaderRecord = DomUtil.GetElementText(domOperLog.DocumentElement, "readerRecord"); XmlDocument readerdom = new XmlDocument(); readerdom.LoadXml(strReaderRecord); string strItemRecord = DomUtil.GetElementText(domOperLog.DocumentElement, "itemRecord"); XmlDocument itemdom = new XmlDocument(); itemdom.LoadXml(strItemRecord); string strItemRecPath = ""; XmlElement item_record = domOperLog.DocumentElement.SelectSingleNode("itemRecord") as XmlElement; if (item_record != null) { strItemRecPath = item_record.GetAttribute("recPath"); } strReaderRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID"); strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode"); // 构造内容 XmlDocument bodydom = new XmlDocument(); bodydom.LoadXml("<root />"); if (strOperation == "borrow") { DomUtil.SetElementText(bodydom.DocumentElement, "type", "借书成功"); } else if (strOperation == "return") { DomUtil.SetElementText(bodydom.DocumentElement, "type", "还书成功"); } else { #if NO strError = "无法识别的 strOperation '" + strOperation + "'"; throw new Exception(strError); #endif DomUtil.SetElementText(bodydom.DocumentElement, "type", "修改交费注释"); strBodyXml = ""; return; } // 复制日志记录中的一级元素 XmlNodeList nodes = domOperLog.DocumentElement.SelectNodes("*"); foreach (XmlNode node in nodes) { if (node.Name == "readerRecord" || node.Name == "itemRecord") { continue; } if (node.Name == "type") { DomUtil.SetElementText(bodydom.DocumentElement, "bookType", node.InnerText); } else { DomUtil.SetElementText(bodydom.DocumentElement, node.Name, node.InnerText); } } { XmlElement record = bodydom.CreateElement("patronRecord"); bodydom.DocumentElement.AppendChild(record); record.InnerXml = readerdom.DocumentElement.InnerXml; DomUtil.DeleteElement(record, "borrowHistory"); DomUtil.DeleteElement(record, "password"); DomUtil.DeleteElement(record, "fingerprint"); DomUtil.DeleteElement(record, "face"); DomUtil.SetElementText(record, "libraryCode", strLibraryCode); } { XmlElement record = bodydom.CreateElement("itemRecord"); bodydom.DocumentElement.AppendChild(record); record.InnerXml = itemdom.DocumentElement.InnerXml; string strItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode"); DomUtil.DeleteElement(record, "borrowHistory"); // 加入书目摘要 string strSummary = ""; string strBiblioRecPath = ""; RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); if (channel == null) { strError = "channel == null"; throw new Exception(strError); } LibraryServerResult result = this.App.GetBiblioSummary( null, channel, strItemBarcode, strItemRecPath, null, out strBiblioRecPath, out strSummary); if (result.Value == -1) { // strSummary = result.ErrorInfo; } else { } DomUtil.SetElementText(record, "summary", strSummary); } strBodyXml = bodydom.DocumentElement.OuterXml; }
// 写入一条数据 // return: // -1 error // 0 已经写入 // 1 没有必要写入 int WriteOneReaderInfo( SessionInfo sessioninfo, string strReaderDbName, string strZhengyuanXml, out string strError) { strError = ""; XmlDocument zhengyuandom = new XmlDocument(); try { zhengyuandom.LoadXml(strZhengyuanXml); } catch (Exception ex) { strError = "从正元数据中读出的XML片段装入DOM失败: " + ex.Message; return(-1); } // AccType // 卡户类型 // 1正式卡,2 临时卡 string strAccType = DomUtil.GetElementText(zhengyuandom.DocumentElement, "ACCTYPE"); if (strAccType != "1") { return(1); } string strBarcode = DomUtil.GetElementText(zhengyuandom.DocumentElement, "ACCNUM"); if (String.IsNullOrEmpty(strBarcode) == true) { strError = "缺乏<ACCNUM>元素"; return(-1); } strBarcode = strBarcode.PadLeft(10, '0'); int nRet = 0; string strReaderXml = ""; string strOutputPath = ""; byte[] baTimestamp = null; // 加读锁 // 可以避免拿到读者记录处理中途的临时状态 #if DEBUG_LOCK_READER this.App.WriteErrorLog("WriteOneReaderInfo 开始为读者加读锁 '" + strBarcode + "'"); #endif this.App.ReaderLocks.LockForRead(strBarcode); try { RmsChannel channel = this.RmsChannels.GetChannel(this.App.WsUrl); if (channel == null) { strError = "get channel error"; return(-1); } // 获得读者记录 // return: // -1 error // 0 not found // 1 命中1条 // >1 命中多于1条 nRet = this.App.GetReaderRecXml( // this.RmsChannels, // sessioninfo.Channels, channel, strBarcode, out strReaderXml, out strOutputPath, out baTimestamp, out strError); } finally { this.App.ReaderLocks.UnlockForRead(strBarcode); #if DEBUG_LOCK_READER this.App.WriteErrorLog("WriteOneReaderInfo 结束为读者加读锁 '" + strBarcode + "'"); #endif } if (nRet == -1) { return(-1); } if (nRet > 1) { strError = "条码号 " + strBarcode + "在读者库群中检索命中 " + nRet.ToString() + " 条,请尽快更正此错误。"; return(-1); } string strAction = ""; string strRecPath = ""; string strNewXml = ""; // 修改后的记录 if (nRet == 0) { // 没有命中,创建新记录 strAction = "new"; strRecPath = strReaderDbName + "/?"; strReaderXml = ""; // 2009/7/17 changed // "<root />"; } else { Debug.Assert(nRet == 1, ""); // 命中,修改后覆盖原记录 strAction = "change"; strRecPath = strOutputPath; } XmlDocument readerdom = new XmlDocument(); try { readerdom.LoadXml(strReaderXml); } catch (Exception ex) { strError = "读者XML记录装入DOM发生错误: " + ex.Message; return(-1); } nRet = ModifyReaderRecord(ref readerdom, zhengyuandom, out strError); if (nRet == -1) { return(-1); } if (nRet == 1) // 没有必要写入 { Debug.Assert(strAction == "change", ""); return(1); } if (nRet == 2) // 没有必要写入 { return(1); } strNewXml = readerdom.OuterXml; string strExistingXml = ""; string strSavedXml = ""; string strSavedRecPath = ""; byte[] baNewTimestamp = null; DigitalPlatform.rms.Client.rmsws_localhost.ErrorCodeValue kernel_errorcode = DigitalPlatform.rms.Client.rmsws_localhost.ErrorCodeValue.NoError; LibraryServerResult result = this.App.SetReaderInfo( sessioninfo, strAction, strRecPath, strNewXml, strReaderXml, baTimestamp, out strExistingXml, out strSavedXml, out strSavedRecPath, out baNewTimestamp, out kernel_errorcode); if (result.Value == -1) { strError = result.ErrorInfo; return(-1); } return(0); // 正常写入了 }