private IFsComplexFeature AddComplexFeature(IFsFeatureSystem featSys, string name, params IFsFeatDefn[] features) { IFsFeatStrucType type = AddFSType(featSys, name, features); IFsComplexFeature feat = Cache.ServiceLocator.GetInstance <IFsComplexFeatureFactory>().Create(); featSys.FeaturesOC.Add(feat); feat.Name.SetAnalysisDefaultWritingSystem(name); feat.Abbreviation.SetAnalysisDefaultWritingSystem(name); feat.TypeRA = type; return(feat); }
/// <summary> /// Recursively builds the feature structure based on contents of treeview node path. /// It recurses back up the treeview node path to the top and then builds the feature structure /// as it goes back down. /// </summary> /// <param name="node"></param> /// <param name="fs"></param> /// <returns></returns> private void BuildFeatureStructure(FeatureTreeNode node, ref IFsFeatStruc fs, ref IFsFeatureSpecification val) { if (node.Parent != null) { BuildFeatureStructure((FeatureTreeNode)node.Parent, ref fs, ref val); } switch (node.Kind) { case FeatureTreeNodeInfo.NodeKind.Complex: IFsComplexValue complex = fs.FindOrCreateComplexValue(node.Hvo); val = complex as FsComplexValue; val.FeatureRAHvo = node.Hvo; if (fs.TypeRA == null) { // this is the type which contains the complex feature fs.TypeRAHvo = FsFeatureSystem.GetTypeFromFsComplexFeature(m_cache, node.Hvo); } fs = (IFsFeatStruc)complex.ValueOA; if (fs.TypeRA == null) { // this is the type of what's being embedded in the fs IFsComplexFeature cf = val.FeatureRA as IFsComplexFeature; if (cf != null) { fs.TypeRA = cf.TypeRA; } } break; case FeatureTreeNodeInfo.NodeKind.Closed: val = (IFsClosedValue)fs.FindOrCreateClosedValue(node.Hvo); val.FeatureRAHvo = node.Hvo; break; case FeatureTreeNodeInfo.NodeKind.SymFeatValue: IFsClosedValue closed = val as IFsClosedValue; if (closed != null) { closed.ValueRAHvo = node.Hvo; } break; default: break; // do nothing } }
private void AddNode(IFsFeatDefn defn, FeatureTreeNode parentNode) { IFsClosedFeature closed = defn as IFsClosedFeature; if (closed != null) { if (!AlreadyInTree(closed.Hvo, parentNode)) { // avoid duplicates FeatureTreeNode newNode = new FeatureTreeNode(closed.Name.AnalysisDefaultWritingSystem, (int)ImageKind.feature, (int)ImageKind.feature, closed.Hvo, FeatureTreeNodeInfo.NodeKind.Closed); InsertNode(newNode, parentNode); foreach (IFsSymFeatVal val in closed.ValuesOC) { AddNode(val, newNode); } } } IFsComplexFeature complex = defn as IFsComplexFeature; if (complex != null) { if (!AlreadyInTree(complex.Hvo, parentNode)) { // avoid infinite loop if a complex feature's type is the same as other features. FeatureTreeNode newNode = new FeatureTreeNode(complex.Name.BestAnalysisAlternative.Text, (int)ImageKind.complex, (int)ImageKind.complex, complex.Hvo, FeatureTreeNodeInfo.NodeKind.Complex); InsertNode(newNode, parentNode); IFsFeatStrucType type = complex.TypeRA; foreach (IFsFeatDefn defn2 in type.FeaturesRS) { AddNode(defn2, newNode); } } } }
public void AddComplexFeaturesToFeatureSystemAndThenToAFeatureStructure() { ILangProject lp = Cache.LangProject; Assert.IsNotNull(lp.MsFeatureSystemOA, "Expect a feature system to be present"); // Set up the xml fs description XmlDocument doc = new XmlDocument(); string sFileDir = Path.Combine(SIL.FieldWorks.Common.Utils.DirectoryFinder.FwSourceDirectory, @"FDO\FDOTests\TestData"); string sFile = Path.Combine(sFileDir, "FeatureSystem2.xml"); doc.Load(sFile); XmlNode itemNeut = doc.SelectSingleNode("//item[@id='vNeut']"); // Add the feature for first time FsFeatureSystem.AddFeatureAsXml(Cache, itemNeut); IFsFeatureSystem msfs = lp.MsFeatureSystemOA; Assert.AreEqual(1, msfs.TypesOC.Count, "should have two types"); Assert.AreEqual(2, msfs.FeaturesOC.Count, "should have two features"); foreach (IFsFeatStrucType type in msfs.TypesOC) { string sName = type.Name.AnalysisDefaultWritingSystem; if (sName != "Subject agreement") { Assert.Fail("Unexpected fs type found: {0}", sName); } Assert.AreEqual(1, type.FeaturesRS.Count, "Expect to have one feature in the type"); IFsFeatDefn defn = (IFsFeatDefn)type.FeaturesRS.FirstItem; Assert.IsNotNull(defn, "first feature in type {0} is not null", sName); IFsComplexFeature complex = defn as IFsComplexFeature; if (complex != null) { Assert.AreEqual("subject agreement", complex.Name.AnalysisDefaultWritingSystem, "Expect name of subject agreement"); } IFsClosedFeature closed = defn as IFsClosedFeature; if (closed != null) { Assert.AreEqual("gender", closed.Name.AnalysisDefaultWritingSystem, "Expect to have gender feature"); foreach (IFsSymFeatVal value in closed.ValuesOC) { Assert.AreEqual("neuter gender", value.Name.AnalysisDefaultWritingSystem, "Expect neuter value"); } } } foreach (IFsFeatDefn defn in msfs.FeaturesOC) { IFsComplexFeature complex = defn as IFsComplexFeature; if (complex != null) { Assert.AreEqual("subject agreement", complex.Name.AnalysisDefaultWritingSystem, "Expect to have subject agreement feature"); } IFsClosedFeature closed = defn as IFsClosedFeature; if (closed != null) { Assert.AreEqual("gender", closed.Name.AnalysisDefaultWritingSystem, "Expect to have gender feature"); foreach (IFsSymFeatVal value in closed.ValuesOC) { Assert.AreEqual("neuter gender", value.Name.AnalysisDefaultWritingSystem, "Expect neuter value"); } } } // Now add a feature that differs only in value XmlNode itemFem = doc.SelectSingleNode("//item[@id='vFem']"); FsFeatureSystem.AddFeatureAsXml(Cache, itemFem); Assert.AreEqual(1, msfs.TypesOC.Count, "should have two types"); Assert.AreEqual(2, msfs.FeaturesOC.Count, "should have two features"); foreach (IFsFeatStrucType type in msfs.TypesOC) { string sName = type.Name.AnalysisDefaultWritingSystem; if (sName != "Subject agreement") { Assert.Fail("Unexpected fs type found: {0}", sName); } } foreach (IFsFeatDefn defn in msfs.FeaturesOC) { IFsComplexFeature complex = defn as IFsComplexFeature; if (complex != null) { Assert.AreEqual("subject agreement", complex.Name.AnalysisDefaultWritingSystem, "Expect to have subject agreement feature"); } IFsClosedFeature closed = defn as IFsClosedFeature; if (closed != null) { Assert.AreEqual("gender", closed.Name.AnalysisDefaultWritingSystem, "Expect to have gender feature"); Assert.AreEqual(2, closed.ValuesOC.Count, "should have two values"); foreach (IFsSymFeatVal cv in closed.ValuesOC) { if (cv.Name.AnalysisDefaultWritingSystem != "neuter gender" && cv.Name.AnalysisDefaultWritingSystem != "feminine gender") { Assert.Fail("Unexpected value found: {0}", cv.Name.AnalysisDefaultWritingSystem); } } } } // now add to feature structure IPartOfSpeech pos = (IPartOfSpeech)lp.PartsOfSpeechOA.PossibilitiesOS.FirstItem; Assert.IsNotNull(pos, "Need one non-null pos"); pos.DefaultFeaturesOA = new FsFeatStruc(); IFsFeatStruc featStruct = pos.DefaultFeaturesOA; // Add the first feature featStruct.AddFeatureFromXml(Cache, itemNeut); Assert.AreEqual("sbj", featStruct.TypeRA.Abbreviation.AnalysisDefaultWritingSystem, "Expect type sbj"); Assert.AreEqual(1, featStruct.FeatureSpecsOC.Count, "should have one feature spec"); foreach (IFsFeatureSpecification fspec in featStruct.FeatureSpecsOC) { IFsComplexValue complex = fspec as IFsComplexValue; Assert.IsNotNull(complex, "Should have non-null complex feature value"); IFsFeatStruc nestedFs = (IFsFeatStruc)complex.ValueOA; Assert.IsNotNull(nestedFs, "Should have non-null nested fs"); foreach (IFsClosedValue cv in nestedFs.FeatureSpecsOC) { Assert.AreEqual("gen", cv.FeatureRA.Abbreviation.AnalysisDefaultWritingSystem, "Expect to have gen feature name"); Assert.AreEqual("n", cv.ValueRA.Abbreviation.AnalysisDefaultWritingSystem, "Expect to have 'n' feature value"); } } // Now add a feature that differs only in value; it should override the old one featStruct.AddFeatureFromXml(Cache, itemFem); Assert.AreEqual("sbj", featStruct.TypeRA.Abbreviation.AnalysisDefaultWritingSystem, "Expect type sbj"); Assert.AreEqual(1, featStruct.FeatureSpecsOC.Count, "should have one feature spec"); foreach (IFsFeatureSpecification fspec in featStruct.FeatureSpecsOC) { IFsComplexValue complex = fspec as IFsComplexValue; Assert.IsNotNull(complex, "Should have non-null complex feature value"); IFsFeatStruc nestedFs = (IFsFeatStruc)complex.ValueOA; Assert.IsNotNull(nestedFs, "Should have non-null nested fs"); foreach (IFsClosedValue cv in nestedFs.FeatureSpecsOC) { if (cv.FeatureRA.Name.AnalysisDefaultWritingSystem != "gender" && cv.ValueRA.Name.AnalysisDefaultWritingSystem != "feminine gender") { Assert.Fail("Unexpected value found: {0}:{1}", cv.FeatureRA.Name.AnalysisDefaultWritingSystem, cv.ValueRA.Name.AnalysisDefaultWritingSystem); } } } // Now add another feature XmlNode item1st = doc.SelectSingleNode("//item[@id='v1']"); featStruct.AddFeatureFromXml(Cache, item1st); Assert.AreEqual("sbj", featStruct.TypeRA.Abbreviation.AnalysisDefaultWritingSystem, "Expect type sbj"); Assert.AreEqual(1, featStruct.FeatureSpecsOC.Count, "should have one feature spec at top feature structure"); foreach (IFsFeatureSpecification fspec in featStruct.FeatureSpecsOC) { IFsComplexValue complex = fspec as IFsComplexValue; Assert.IsNotNull(complex, "Should have non-null complex feature value"); IFsFeatStruc nestedFs = (IFsFeatStruc)complex.ValueOA; Assert.IsNotNull(nestedFs, "Should have non-null nested fs"); Assert.AreEqual(2, nestedFs.FeatureSpecsOC.Count, "should have two feature specs in nested feature structure"); foreach (IFsClosedValue cv in nestedFs.FeatureSpecsOC) { if (!(((cv.FeatureRA.Name.AnalysisDefaultWritingSystem == "gender") && (cv.ValueRA.Name.AnalysisDefaultWritingSystem == "feminine gender")) || ((cv.FeatureRA.Name.AnalysisDefaultWritingSystem == "person") && (cv.ValueRA.Name.AnalysisDefaultWritingSystem == "first person")))) { Assert.Fail("Unexpected value found: {0}:{1}", cv.FeatureRA.Name.AnalysisDefaultWritingSystem, cv.ValueRA.Name.AnalysisDefaultWritingSystem); } } } // Update inflectable features on pos pos.AddInflectableFeatsFromXml(Cache, itemNeut); Assert.AreEqual(1, pos.InflectableFeatsRC.Count, "should have 1 inflectable feature in pos"); foreach (IFsFeatDefn defn in pos.InflectableFeatsRC) { IFsComplexFeature complex = defn as IFsComplexFeature; if (complex != null) { Assert.AreEqual("subject agreement", complex.Name.AnalysisDefaultWritingSystem, "expect to find subject agreement in pos inflectable features"); } } // Check for correct ShortName string in complex Assert.AreEqual("1 f", featStruct.ShortName, "Incorrect ShortName for complex"); // Check for correct LongName string in complex Assert.AreEqual("[sbj:[pers:1 gen:f]]", featStruct.LongName, "Incorrect LongName for complex"); // Now add a closed feature not at the same level sFile = Path.Combine(sFileDir, "FeatureSystem3.xml"); doc = null; doc = new XmlDocument(); doc.Load(sFile); XmlNode itemAorist = doc.SelectSingleNode("//item[@id='xAor']"); FsFeatureSystem.AddFeatureAsXml(Cache, itemAorist); pos.AddInflectableFeatsFromXml(Cache, itemAorist); featStruct.AddFeatureFromXml(Cache, itemAorist); // Check for correct LongName Assert.AreEqual("[asp:aor sbj:[pers:1 gen:f]]", featStruct.LongName, "Incorrect LongName for complex and closed"); // Now add the features in the featurs struct in a different order pos.DefaultFeaturesOA = null; pos.DefaultFeaturesOA = new FsFeatStruc(); featStruct = pos.DefaultFeaturesOA; featStruct.AddFeatureFromXml(Cache, itemAorist); featStruct.AddFeatureFromXml(Cache, item1st); featStruct.AddFeatureFromXml(Cache, itemFem); // check for correct short name Assert.AreEqual("f 1 aor", featStruct.ShortName, "Incorrect ShortName for complex"); // Check for correct LongName Assert.AreEqual("[sbj:[gen:f pers:1] asp:aor]", featStruct.LongName, "Incorrect LongName for complex and closed"); }
public ComplexFeatureNode(IFsComplexFeature feature) { m_feature = feature; }