using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Collections; using TRACEROBJECTLib; using System.Data.OracleClient; namespace CCSTrace.CCS.EventAI { public class TraceSubject { static String DEFAULTDBSTR; static bool IsNewCase; static ArrayList m_LinkList; // store the switch of the new case path static TraceEngine m_tEngine; static Hashtable m_TreeMap; // store the switch of the old case path static int s_Fsc; static int s_Ufid; private RecordLog _Plogger; private ArrayList m_Tmp = new ArrayList(); private NetworkContext m_pContext; private OracleConnection _ConnectionTPC = null; private OracleTransaction _Transaction; public TraceSubject(OracleConnection _Conn, OracleTransaction _Trx, RecordLog _Log) { _ConnectionTPC = _Conn; _Transaction = _Trx; _Plogger = _Log; try { if (m_tEngine == null) { m_tEngine = new TraceEngine(); } } catch (Exception ex) { _Plogger.Error(ex.Message); throw ex; } } public void discardEngine() { if (m_tEngine != null) { m_tEngine = null; } } public ArrayList getNewResult() { return m_LinkList; } public Hashtable getOldResult() { return m_TreeMap; } // for EOS(only get the reverse tree) public void startTrace(int Start_Fsc, int Start_Ufid, bool m_IsNew) { s_Fsc = Start_Fsc; s_Ufid = Start_Ufid; IsNewCase = m_IsNew; m_TreeMap = new Hashtable(); m_LinkList = new ArrayList(); try { this.setReverseTree(Trace(true)); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); throw e; } } private bool getSwitchOn(int UFID) { String SqlStmt; SqlStmt = "SELECT M.OSTATUS as OSTATUS FROM (SELECT UFID,OSTATUS FROM BASEDB.CONNECTIVITY WHERE FSC = 114) M," + "BASEDB.SWITCH S WHERE M.UFID = S.UFID AND S.NSTATUS <> 0 AND M.UFID = " + UFID; OracleCommand Command = null; OracleDataReader reader = null; try { Command = new OracleCommand(SqlStmt, _ConnectionTPC, _Transaction); reader = Command.ExecuteReader(); if (reader.Read()) { if (Convert.ToInt32(reader["OSTATUS"]) == 1) return true; } reader.Close(); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); } finally { if (Command != null) Command.Dispose(); if (reader != null) reader.Close(); } return false; } private bool getJumperOn(int UFID) { String SqlStmt; SqlStmt = "SELECT OSTATUS FROM BASEDB.CONNECTIVITY WHERE FSC = 109 AND UFID = " + UFID; OracleCommand Command = null; OracleDataReader reader = null; try { Command = new OracleCommand(SqlStmt, _ConnectionTPC, _Transaction); reader = Command.ExecuteReader(); if (reader.Read()) { if (Convert.ToInt32(reader["OSTATUS"]) == 1) return true; } reader.Close(); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); } finally { if (Command != null) Command.Dispose(); if (reader != null) reader.Close(); } return false; } private Hashtable TraceCounts = new Hashtable(); private void setReverseTree(ResultTree tree) { int i = 0; TreeIterator iti = null; bool ostatus = true; if (tree != null) { i = 0; iti = tree.CreateTreeIterator(); bool isNotEnd = true; while (isNotEnd) { if (getTraceCount(iti.Value.ClassID, iti.Value.ObjectID) > 5) throw new TraceLoopException("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + iti.Value.ClassID + "," + iti.Value.ObjectID + ")"); else AddTraceCount(iti.Value.ClassID, iti.Value.ObjectID); while (iti.IsLeaf == 0) { TRACEROBJECTLib.TreeNode node = iti.Value; if ((node.ClassID == 114) || (node.ClassID == 108) || (node.ClassID == 109)) { Equipment Equip = new Equipment(node.ClassID, node.ObjectID); if (IsNewCase) m_LinkList.Add(Equip); else { m_TreeMap.Add(node.ObjectID, Equip); m_Tmp.Add(Equip); } i++; /* if (getTraceCount(node.ClassID, node.ObjectID) > 2) throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")"); else AddTraceCount(node.ClassID, node.ObjectID); */ } Console.WriteLine(node.ClassID + "----->" + node.ObjectID); _Plogger.Info(node.ClassID + "----->" + node.ObjectID); iti.MoveDescent((short) 0); } // 當從breaker出來的導線不只一條時,breaker可能會不被add(因為breaker是leaf但其parent的DescentCount > 1,所以被忽略) /* * if ( ((com.origo.TraceModel.ITreeNode)iti.get_Value()).get_ClassID() == EOS.LocalVariable.Breaker ) { * com.origo.TraceModel.ITreeNode node = iti.get_Value(); Equipment Equip = new Equipment(node.get_ClassID(),node.get_ObjectID()); if ( * IsNewCase ) m_LinkList.add(i,Equip); else { m_TreeMap.put(new Integer(node.get_ObjectID()),Equip); m_Tmp.add(Equip); } * System.out.println(node.get_ClassID() + "----->" + node.get_ObjectID()); System.out.println("Trace Finish...."); i++; break; } */ if ((iti.Value).ClassID == CCS.LocalVariable.Breaker) { TRACEROBJECTLib.TreeNode node = iti.Value; Equipment Equip = new Equipment(node.ClassID, node.ObjectID); if (IsNewCase) m_LinkList.Add(Equip); else { m_TreeMap.Add(node.ObjectID, Equip); m_Tmp.Add(Equip); } i++; //後面直接就FINISH,所以就不用判斷tracecount Console.WriteLine(node.ClassID + "----->" + node.ObjectID); _Plogger.Info(node.ClassID + "----->" + node.ObjectID); Console.WriteLine("Trace Finish...."); _Plogger.Info("Trace Finish...."); break; } // 當追蹤到被切開的開關且該上一層設備只有該開關一個child) else if (iti.Value.ClassID == CCS.LocalVariable.Switch || iti.Value.ClassID == CCS.LocalVariable.Jumper ) { TRACEROBJECTLib.TreeNode node = iti.Value; iti.MoveAscent(); Equipment Equip = new Equipment(node.ClassID, node.ObjectID); if (isEndEquip(Equip)) { if (IsNewCase) m_LinkList.Add(Equip); else { m_TreeMap.Add(node.ObjectID, Equip); m_Tmp.Add(Equip); } i++; //後面直接就FINISH,所以就不用判斷tracecount Console.WriteLine(node.ClassID + "----->" + node.ObjectID); _Plogger.Info(node.ClassID + "----->" + node.ObjectID); Console.WriteLine("Trace Finish...."); _Plogger.Info("Trace Finish...."); break; } //switch (node.ClassID) //{ // case 114: // ostatus = getSwitchOn(node.ObjectID); // break; // case 109: // ostatus = getJumperOn(node.ObjectID); // break; //} //if (!ostatus && (iti.DescentCount == 1)) { // Equipment Equip = new Equipment(node.ClassID, node.ObjectID); // if (IsNewCase) // m_LinkList.Add(Equip); // else { // m_TreeMap.Add(node.ObjectID, Equip); // m_Tmp.Add(Equip); // } // i++; // Console.WriteLine(node.ClassID + "----->" + node.ObjectID); // _Plogger.Info(node.ClassID + "----->" + node.ObjectID); // Console.WriteLine("Trace Finish...."); // _Plogger.Info("Trace Finish...."); // break; //} } else { TRACEROBJECTLib.TreeNode node = iti.Value; iti.MoveAscent(); if (iti.DescentCount == 1) throw new Exception("追蹤到非開關類斷開之設備(Fsc = " + node.ClassID + ",Ufid = " + node.ObjectID); } for (int j = 1; j < iti.DescentCount; j++) { iti.MoveDescent((short) j); if (iti.IsLeaf == 1) { TRACEROBJECTLib.TreeNode node = iti.Value; Equipment Equip = new Equipment(node.ClassID, node.ObjectID); switch (node.ClassID) { case 108: if (IsNewCase) m_LinkList.Add(Equip); else { m_TreeMap.Add(node.ObjectID, Equip); m_Tmp.Add(Equip); } Console.WriteLine(node.ClassID + "----->" + node.ObjectID); _Plogger.Info(node.ClassID + "----->" + node.ObjectID); i++; /* if (getTraceCount(node.ClassID, node.ObjectID) > 2) throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")"); else AddTraceCount(node.ClassID, node.ObjectID); */ break; case 109: case 114: switch (node.ClassID) { case 114: ostatus = getSwitchOn(node.ObjectID); break; case 109: ostatus = getJumperOn(node.ObjectID); break; } // Only for switch because the breaker only has one node to descent if (!ostatus) { if (IsNewCase) m_LinkList.Add(Equip); else { m_TreeMap.Add(node.ObjectID, Equip); m_Tmp.Add(Equip); } Console.WriteLine(node.ClassID + "----->" + node.ObjectID); _Plogger.Info(node.ClassID + "----->" + node.ObjectID); i++; /* if (getTraceCount(node.ClassID, node.ObjectID) > 2) throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")"); else AddTraceCount(node.ClassID, node.ObjectID); */ } break; default: break; } // switch iti.MoveAscent(); isNotEnd = false; } else { isNotEnd = true; break; } } // for } // while Console.WriteLine("Tree Node Count = " + i); _Plogger.Info("Tree Node Count = " + i); } else { Console.WriteLine("Tree is null"); _Plogger.Info("Tree is null"); throw new Exception("無法追蹤到任何設備,可能是該用戶所在變壓器設備連結性有問題。"); } } private ResultTree Trace(bool Reverse) { ResultTree tree = null; try { configTrace(); _Plogger.Info("configTrace OK."); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); return tree; } try { tree = ModeTrace(Reverse); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); } return tree; } void configTrace() { if (DEFAULTDBSTR == null) { DEFAULTDBSTR = "basedb/basedb000@nntpc"; } try { if (m_pContext == null) m_pContext = m_tEngine.teoCreateContext(); if (m_pContext.IsConnected == 0) { m_pContext.Connect("", DEFAULTDBSTR); } } catch (Exception ex) { _Plogger.Error(ex.Message); } } private ResultTree ModeTrace(bool Reverse) { TravelContext tContext = new TravelContext(); TravelStartCriterion sCriterion = new TravelStartCriterion(); TravelTerminateCriterion eCriterion = new TravelTerminateCriterion(); sCriterion.ClsID = (short) s_Fsc; sCriterion.ObjID = s_Ufid; if (Reverse) // 反向上追 { sCriterion.StartMode = (TRAVELSTARTCRITERIONTYPE)(Convert.ToInt32(TRAVELSTARTCRITERIONTYPE.TRAVELBYNEGDIR) + Convert.ToInt32(TRAVELSTARTCRITERIONTYPE.TRAVELWITHFOLLOW)); eCriterion.ClsID = (short)CCS.LocalVariable.Breaker; eCriterion.EndMode = TRAVELTERMCRITERIONTYPE.TRAVELTOTHISCLASS; } else // 順向追蹤 { sCriterion.StartMode = TRAVELSTARTCRITERIONTYPE.TRAVELBYCURDIR; eCriterion.EndMode = TRAVELTERMCRITERIONTYPE.TRAVELTOTHISCLASS; } tContext.addCriterion(sCriterion); tContext.addCriterion(eCriterion); m_pContext.ResetContext(); _Plogger.Info("Set ModeTrace OK."); ResultTreeBuilder trBuilder = m_pContext.CreateTreeBuilder(); if (!trBuilder.constructResultTree(tContext, TRAVELTHREADMODE.CONMODE_SYNCHRONOUS)) { return null; } _Plogger.Info("ConstructResultTree OK."); ResultTree result = trBuilder.ResultTree; _Plogger.Info("getResultTree OK."); return result; } //判斷是否為最終設備(逆向追到已經無child的設備時,檢查該設備是否為最終設備(查驗該設備的同層設備,是否仍有可繼續逆向追蹤的設備,若無,則該設備為最終設備 private bool isEndEquip(Equipment SelfEquip) { String SqlStmt; OracleCommand Command = null; OracleDataReader reader = null; long N_Value = 0; SqlStmt = "SELECT DIR,OSTATUS,N1,N2 FROM BASEDB.CONNECTIVITY WHERE FSC = " + SelfEquip.getFSC() + " AND UFID = " + SelfEquip.getUFID(); try { Command = new OracleCommand(SqlStmt, _ConnectionTPC, _Transaction); reader = Command.ExecuteReader(); if (reader.Read()) { if (Convert.ToInt32(reader["OSTATUS"]) == 1) //如果設備本身為非切開的設備,那應該繼續往逆向追 return false; else { if (Convert.ToInt32(reader["DIR"]) == 3) //順向無電 N1-->N2,所以逆向的上游N值抓N2 N_Value = Convert.ToInt32(reader["N2"]); else N_Value = Convert.ToInt32(reader["N1"]); } } reader.Close(); SqlStmt = "SELECT FSC,UFID,DIR,OSTATUS,N1,N2 FROM BASEDB.CONNECTIVITY WHERE N1 <> N2 AND ( N1 = " + N_Value + " OR N2 = " + N_Value + ")"; Command.CommandText = SqlStmt; reader = Command.ExecuteReader(); while (reader.Read()) { if (Convert.ToInt32(reader["FSC"]) == SelfEquip.getFSC() && Convert.ToInt32(reader["UFID"]) == SelfEquip.getUFID()) continue; if (Convert.ToInt32(reader["OSTATUS"]) == 0) //切開的設備不可能為逆向的上游 continue; if (Convert.ToInt32(reader["N1"]) == N_Value) { switch (Convert.ToInt32(reader["DIR"])) { case 1: case 3: break; case 2: case 4: return false; //如果逆向的上游連接點為N1,一定要N2-->N1才可能還有需要逆向追蹤設備 case 99: break; //未供電設備不可能是逆向上游 } } else if (Convert.ToInt32(reader["N2"]) == N_Value) { switch (Convert.ToInt32(reader["DIR"])) { case 1: case 3: return false; //如果逆向的上游連接點為N2,一定要N1-->N2才可能還有需要逆向追蹤設備 case 2: case 4: break; case 99: return false; //未供電設備不可能是逆向上游 } } } reader.Close(); } catch (Exception e) { _Plogger.Error(e.Message); Console.WriteLine(e.StackTrace); return false; } finally { if (Command != null) Command.Dispose(); if (reader != null) reader.Close(); } return true; } private int getTraceCount(int Fsc, int Ufid) { if (TraceCounts.ContainsKey(Fsc + "|" + Ufid)) return Int32.Parse(TraceCounts[Fsc + "|" + Ufid].ToString()); else return 0; } private void AddTraceCount(int Fsc, int Ufid) { int Count = 1; if (TraceCounts.ContainsKey(Fsc + "|" + Ufid)) { Count = Int32.Parse(TraceCounts[Fsc + "|" + Ufid].ToString()); Count++; TraceCounts.Remove(Fsc + "|" + Ufid); } TraceCounts.Add(Fsc + "|" + Ufid, Count.ToString()); } } public class TraceLoopException : Exception { public String Message = ""; public TraceLoopException(String _Message) { Message = _Message; } } }