public static dynamic FetchReplacementValue(ResolveOptions resOpt, dynamic oldValue, dynamic newValue, bool wasSet) { if (oldValue == null) { return(newValue); } if (!wasSet) { // must explicitly set a value to override // if a new value is not set, then newValue holds nothing or the default. // in this case, if there was already a value in this argument then just keep using it. return(oldValue); } if (oldValue is string) { return(newValue); } CdmObject ov = oldValue as CdmObject; CdmObject nv = newValue as CdmObject; // replace an old table with a new table? actually just mash them together if (ov != null && ov.ObjectType == CdmObjectType.EntityRef && nv != null && nv.GetType() != typeof(string) && nv.ObjectType == CdmObjectType.EntityRef) { var oldEnt = ov.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt); var newEnt = nv.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt); // check that the entities are the same shape if (newEnt == null) { return(ov); } // BUG CdmEntityDefinition entDefShape = null; if (oldEnt == null || ((entDefShape = oldEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt)) != newEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt))) { return(nv); } var oldCv = oldEnt.ConstantValues; var newCv = newEnt.ConstantValues; // rows in old? if (oldCv == null || oldCv.Count == 0) { return(nv); } // rows in new? if (newCv == null || newCv.Count == 0) { return(ov); } // make a set of rows in the old one and add the new ones. this will union the two // find rows in the new one that are not in the old one. slow, but these are small usually IDictionary <string, List <string> > unionedRows = new Dictionary <string, List <string> >(); // see if any of the entity atts are the primary key, meaning, the only thing that causes us to merge dups unique. // i know this makes you think about a snake eating its own tail, but fetch the resolved attributes of the constant shape int pkAtt = -1; if (entDefShape != null) { var resOptShape = new ResolveOptions(entDefShape.InDocument); var resAttsShape = entDefShape.FetchResolvedAttributes(resOptShape); if (resAttsShape != null) { pkAtt = resAttsShape.Set.FindIndex((ra) => ra.ResolvedTraits.Find(resOptShape, "is.identifiedBy") != null); } } for (int i = 0; i < oldCv.Count; i++) { List <string> row = oldCv[i]; string key; // the entity might have a PK, if so, only look at that values as the key if (pkAtt != -1) { key = row[pkAtt]; } else { key = row.Aggregate((prev, curr) => { return($"{(!string.IsNullOrEmpty(prev) ? prev : "")}::{curr}"); }); } unionedRows[key] = row; } for (int i = 0; i < newCv.Count; i++) { List <string> row = newCv[i]; string key; // the entity might have a PK, if so, only look at that values as the key if (pkAtt != -1) { key = row[pkAtt]; } else { key = row.Aggregate((prev, curr) => { return($"{(!string.IsNullOrEmpty(prev) ? prev : "")}::{curr}"); }); } unionedRows[key] = row; } if (unionedRows.Count == oldCv.Count) { return(ov); } List <List <string> > allRows = unionedRows.Values.ToList(); CdmConstantEntityDefinition replacementEnt = (CdmConstantEntityDefinition)oldEnt.Copy(resOpt); replacementEnt.ConstantValues = allRows; return(resOpt.WrtDoc.Ctx.Corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, replacementEnt, false)); } return(newValue); }
public static dynamic FetchReplacementValue(ResolveOptions resOpt, dynamic oldValue, dynamic newValue, bool wasSet) { if (oldValue == null) { return(newValue); } if (!wasSet) { // must explicitly set a value to override // if a new value is not set, then newValue holds nothing or the default. // in this case, if there was already a value in this argument then just keep using it. return(oldValue); } if (oldValue is string) { return(newValue); } CdmObject ov = oldValue as CdmObject; CdmObject nv = newValue as CdmObject; // replace an old table with a new table? actually just mash them together if (ov != null && ov.ObjectType == CdmObjectType.EntityRef && nv != null && nv.GetType() != typeof(string) && nv.ObjectType == CdmObjectType.EntityRef) { var oldEnt = ov.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt); var newEnt = nv.FetchObjectDefinition <CdmConstantEntityDefinition>(resOpt); // check that the entities are the same shape if (newEnt == null) { return(ov); } // BUG if (oldEnt == null || (oldEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt) != newEnt.EntityShape.FetchObjectDefinition <CdmEntityDefinition>(resOpt))) { return(nv); } var oldCv = oldEnt.ConstantValues; var newCv = newEnt.ConstantValues; // rows in old? if (oldCv == null || oldCv.Count == 0) { return(nv); } // rows in new? if (newCv == null || newCv.Count == 0) { return(ov); } // make a set of rows in the old one and add the new ones. this will union the two // find rows in the new one that are not in the old one. slow, but these are small usually IDictionary <string, List <string> > unionedRows = new Dictionary <string, List <string> >(); for (int i = 0; i < oldCv.Count; i++) { List <string> row = oldCv[i]; string key = row.Aggregate((prev, curr) => { StringBuilder result = new StringBuilder(!string.IsNullOrEmpty(prev) ? prev : ""); result.Append("::"); result.Append(curr); return(result.ToString()); }); unionedRows[key] = row; } for (int i = 0; i < newCv.Count; i++) { List <string> row = newCv[i]; string key = row.Aggregate((prev, curr) => { StringBuilder result = new StringBuilder(!string.IsNullOrEmpty(prev) ? prev : ""); result.Append("::"); result.Append(curr); return(result.ToString()); }); unionedRows[key] = row; } if (unionedRows.Count == oldCv.Count) { return(ov); } List <List <string> > allRows = unionedRows.Values.ToList(); CdmConstantEntityDefinition replacementEnt = (CdmConstantEntityDefinition)oldEnt.Copy(resOpt); replacementEnt.ConstantValues = allRows; return(resOpt.WrtDoc.Ctx.Corpus.MakeRef <CdmEntityReference>(CdmObjectType.EntityRef, replacementEnt, false)); } return(newValue); }