mrksbrg/ImpRec

View on GitHub
Logic/KnowlBase.cs

Summary

Maintainability
A
3 hrs
Test Coverage
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Xml;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

// Lucene
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Directory = Lucene.Net.Store.Directory;
using Version = Lucene.Net.Util.Version;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;

namespace ImpRec
{
    /// <summary>
    /// Represents the knowledge base, the project memory as parsed from the input files.
    /// </summary>
    [Serializable()]
    public class KnowlBase : ISerializable
    {
        private string LUCENEDIR = "LuceneIndex";

        private TextWriter textWriter;
        private XmlWriter xmlWriter;
        private XmlWriter graphMLWriter;

        public Hashtable caseMap;
        public Hashtable artifactMap;

        private int nbrRelatedCaseLinks;
        private int nbrSpecifiedByLinks;
        private int nbrVerifiedByLinks;
        private int nbrNeedsUpdateLinks;
        private int nbrImpactedHWLinks;
        private int nbrUnspecifiedLinks;

        private Directory luceneDirectory;
        private Analyzer luceneAnalyzer;
        private IndexSearcher luceneIndexSearcher;

        public KnowlBase()
        {
            caseMap = new Hashtable();
            artifactMap = new Hashtable();

            // Make sure there is a directory for the Lucene index
            if (!System.IO.Directory.Exists(LUCENEDIR))
            {
                System.IO.Directory.CreateDirectory(LUCENEDIR);
            }

            luceneDirectory = FSDirectory.Open(new DirectoryInfo(LUCENEDIR));
            luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_30);
            luceneIndexSearcher = null;
        }

        #region Serialization
        public KnowlBase(SerializationInfo info, StreamingContext ctxt)
        {
            this.textWriter = (TextWriter)info.GetValue("TextWriter", typeof(TextWriter));
            this.xmlWriter = (XmlWriter)info.GetValue("XmlWriter", typeof(XmlWriter));
            this.graphMLWriter = (XmlWriter)info.GetValue("GraphMLWriter", typeof(XmlWriter));
            this.caseMap = (Hashtable)info.GetValue("CaseMap", typeof(Hashtable));
            this.artifactMap = (Hashtable)info.GetValue("ArtifactMap", typeof(Hashtable));
            this.nbrRelatedCaseLinks = (int)info.GetValue("NbrRelatedCaseLinks", typeof(int));
            this.nbrSpecifiedByLinks = (int)info.GetValue("NbrSpecifiedByLinks", typeof(int));
            this.nbrVerifiedByLinks = (int)info.GetValue("NbrVerifiedByLinks", typeof(int));
            this.nbrNeedsUpdateLinks = (int)info.GetValue("NbrNeedsUpdateLinks", typeof(int));
            this.nbrImpactedHWLinks = (int)info.GetValue("NbrImpactedHWLinks", typeof(int));
            this.nbrUnspecifiedLinks = (int)info.GetValue("NbrUnspecifiedLinks", typeof(int));
            luceneDirectory = FSDirectory.Open(new DirectoryInfo("LuceneIndex"));
            luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_30);
            luceneIndexSearcher = null;
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("TextWriter", this.textWriter);
            info.AddValue("XmlWriter", this.xmlWriter);
            info.AddValue("GraphMLWriter", this.graphMLWriter);
            info.AddValue("CaseMap", this.caseMap);
            info.AddValue("ArtifactMap", this.artifactMap);
            info.AddValue("NbrRelatedCaseLinks", this.nbrRelatedCaseLinks);
            info.AddValue("NbrSpecifiedByLinks", this.nbrSpecifiedByLinks);
            info.AddValue("NbrVerifiedByLinks", this.nbrVerifiedByLinks);
            info.AddValue("NbrNeedsUpdateLinks", this.nbrNeedsUpdateLinks);
            info.AddValue("NbrImpactedHWLinks", this.nbrImpactedHWLinks);
            info.AddValue("NbrUnspecifiedLinks", this.nbrUnspecifiedLinks);
        }
        #endregion

        /// <summary>
        /// Add a new TrackerCase to the knowledge base.
        /// </summary>
        /// <param name="tc"></param>
        /// <returns></returns>
        public bool AddTrackerCase(TrackerCase tc)
        {
            bool found = false;

            foreach (TrackerCase tmp in caseMap.Values)
            {
                if (tc.ArtifactID.Equals(tmp.ArtifactID))
                {
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                caseMap.Add(tc.ArtifactID, tc);
            }

            return !found;
        }

        /// <summary>
        /// Add a new ImpactItem to the knowledge base.
        /// </summary>
        /// <param name="sa"></param>
        /// <returns></returns>
        public bool AddArtifact(ImpactItem sa)
        {
            bool found = false;
            foreach (SoftwareArtifact tmp in artifactMap.Values)
            {
                // If we have encountered the artifact before, but not been able to determine its type, do it now.
                if (sa.ArtifactID.Equals(tmp.ArtifactID))
                {
                    ++sa.NbrInLinks;
                    if (tmp.Type.Equals("UNKNOWN"))
                    {
                        tmp.Type = sa.Type;
                    }
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                sa.NbrInLinks = 1;
                artifactMap.Add(sa.ArtifactID, sa);
            }
            return !found;
        }

        public TrackerCase GetTrackerCase(string id, bool evalMode)
        {
            if (id[0] == '#')
            {
                id = id.Remove(0, 1);
            }

            TrackerCase tc = (TrackerCase)caseMap[id];
            return (TrackerCase)caseMap[id];
        }

        public ImpactItem GetImpactItem(string id)
        {
            return (ImpactItem)artifactMap[id];
        }

        /// <summary>
        /// Analyze how a specific tracker case impacted artifacts in the past.
        /// </summary>
        /// <param name="caseID">ID of tracker case to analyze</param>
        /// <param name="similarity">How similar this tracker case is to the input case as calculated by Lucene</param>
        /// <param name="evalMode">Toggle evaluation mode, using only 90% of the available data</param>
        /// <returns>A linked list of impacted artifacts</returns>
        public LinkedList<ImpactItem> AnalyzeImpact(string caseID, double similarity, bool evalMode)
        {
            // Clear all visits
            foreach (TrackerCase tc in caseMap.Values)
            {
                tc.Visited = false;
            }

            LinkedList<ImpactItem> impactList = new LinkedList<ImpactItem>();
            TrackerCase startCase = GetTrackerCase(caseID, evalMode);        

            if (startCase != null)
            {
                impactList = startCase.FindImpact(impactList, 1, similarity);
            }
            return impactList;
        }

        public void IndexKnowlBase()
        {
            var writer = new IndexWriter(luceneDirectory, luceneAnalyzer, true, IndexWriter.MaxFieldLength.LIMITED);

            foreach (TrackerCase tc in caseMap.Values)
            {
                // Create Lucene document
                var trackerDocument = new Document();
                Field idField = new Field("ID", tc.ArtifactID, Field.Store.YES, Field.Index.NOT_ANALYZED);
                trackerDocument.Add(idField);
                Field titleField = new Field("Title", tc.Title, Field.Store.YES, Field.Index.ANALYZED);
                //titleField.Boost = 1.2F;
                trackerDocument.Add(titleField);
                Field descField = new Field("Description", tc.Description, Field.Store.YES, Field.Index.ANALYZED);
                trackerDocument.Add(descField);

                // Add Lucene document to index
                writer.AddDocument(trackerDocument);
            }

            writer.Optimize();
            writer.Dispose();
        }

        public ScoreDoc[] IdentifySimilarIssue(string queryText)
        {
            IndexReader indexReader = IndexReader.Open(luceneDirectory, true);
            luceneIndexSearcher = new IndexSearcher(indexReader);

            var queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new string[] { "Title", "Description" }, luceneAnalyzer);
            Query query = null;
            try
            {
                query = queryParser.Parse(queryText);
            }
            catch (Exception exc)
            {
                return new ScoreDoc[0]; 
            }

            TopDocs resultDocs = luceneIndexSearcher.Search(query, indexReader.MaxDoc);

            luceneIndexSearcher.Dispose();

            return resultDocs.ScoreDocs;
        }

        public IndexSearcher GetIndexSearcher()
        {
            return luceneIndexSearcher;
        }

        public int GetNbrTrackerCases()
        {
            return caseMap.Count;
        }

        public int GetNbrImpactItems()
        {
            return artifactMap.Count;
        }

        public int GetTotLinks()
        {
            return nbrRelatedCaseLinks + nbrSpecifiedByLinks + nbrVerifiedByLinks + nbrNeedsUpdateLinks + nbrImpactedHWLinks + nbrUnspecifiedLinks;
        }

        public int NbrRelatedCaseLinks
        {
            get { return nbrRelatedCaseLinks; }
            set { nbrRelatedCaseLinks = value; }
        }
        public int NbrSpecifiedByLinks
        {
            get { return nbrSpecifiedByLinks; }
            set { nbrSpecifiedByLinks = value; }
        }
        public int NbrVerifiedByLinks
        {
            get { return nbrVerifiedByLinks; }
            set { nbrVerifiedByLinks = value; }
        }
        public int NbrNeedsUpdateLinks
        {
            get { return nbrNeedsUpdateLinks; }
            set { nbrNeedsUpdateLinks = value; }
        }
        public int NbrImpactedHWLinks
        {
            get { return nbrImpactedHWLinks; }
            set { nbrImpactedHWLinks = value; }
        }
        public int NbrUnspecifiedLinks
        {
            get { return nbrUnspecifiedLinks; }
            set { nbrUnspecifiedLinks = value; }
        }
    }

}