/// <inheritdoc /> public override bool Visit(string pathFrom, VisitCallback preChildren, VisitCallback postChildren) { string path = string.Empty; if (this.Ctx.Corpus.blockDeclaredPathChanges == false) { path = this.DeclaredPath; if (string.IsNullOrEmpty(path)) { path = pathFrom + this.Name; this.DeclaredPath = path; } } if (preChildren?.Invoke(this, path) == true) { return(false); } if (this.Parent?.Visit(path + "/parent/", preChildren, postChildren) == true) { return(true); } if (this.Definition?.Visit(path + "/definition/", preChildren, postChildren) == true) { return(true); } if (this.Contents != null && CdmObjectBase.VisitList(this.Contents, path + "/", preChildren, postChildren)) // fix that as any. { return(true); } if (this.VisitDef(path, preChildren, postChildren)) { return(true); } if (postChildren != null && postChildren.Invoke(this, path)) { return(true); } return(false); }
/// <summary> /// Clear all document's internal caches and update the declared path of every object contained by this document. /// </summary> /// <param name="objects"></param> /// <returns>A list containing all the objects inside this document.</returns> internal void ClearCaches() { // Clean all internal caches and flags this.InternalObjects = new List <CdmObjectBase>(); this.DeclarationsIndexed = false; this.InternalDeclarations = new ConcurrentDictionary <string, CdmObjectBase>(); this.ImportsIndexed = false; this.ImportPriorities = null; // Collects all the objects contained by this document and updates their DeclaredPath. this.Visit("", new VisitCallback { Invoke = (obj, objPath) => { CdmObjectBase objectBase = obj as CdmObjectBase; // Update the DeclaredPath property. objectBase.DeclaredPath = objPath; this.InternalObjects.Add(objectBase); return(false); } }, null); }
/// <inheritdoc /> public override bool Visit(string pathFrom, VisitCallback preChildren, VisitCallback postChildren) { string path = this.UpdateDeclaredPath(pathFrom); if (preChildren?.Invoke(this, path) == true) { return(false); } if (this.Parent?.Visit(path + "/parent/", preChildren, postChildren) == true) { return(true); } if (this.Definition?.Visit(path + "/definition/", preChildren, postChildren) == true) { return(true); } if (this.Contents != null && CdmObjectBase.VisitList(this.Contents, path + "/", preChildren, postChildren)) // fix that as any. { return(true); } if (this.Lineage != null && CdmObjectBase.VisitList(this.Lineage, path + "/lineage/", preChildren, postChildren)) // fix that as any. { return(true); } if (this.VisitDef(path, preChildren, postChildren)) { return(true); } if (postChildren != null && postChildren.Invoke(this, path)) { return(true); } return(false); }
public static CdmAttributeContext InstanceFromData(CdmCorpusContext ctx, dynamic obj) { return(CdmObjectBase.InstanceFromData <CdmAttributeContext, dynamic>(ctx, obj)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmTypeAttributeDefinition>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt = null, CopyOptions options = null) { return(CdmObjectBase.CopyData <CdmProjection>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmReferencedEntityDeclarationDefinition>(this, resOpt, options)); }
public static CdmImport InstanceFromData(CdmCorpusContext ctx, Import import) { return(CdmObjectBase.InstanceFromData <CdmImport, Import>(ctx, import)); }
/// <summary> /// Checks if the trait argumnet value matchs the data type defined on the trait parameter /// </summary> /// <param name="resOpt"></param> /// <param name="wrtDoc"></param> /// <param name="argumentValue"></param> /// <returns></returns> internal dynamic ConstTypeCheck(ResolveOptions resOpt, CdmDocumentDefinition wrtDoc, dynamic argumentValue) { ResolveContext ctx = this.Ctx as ResolveContext; dynamic replacement = argumentValue; // if parameter type is entity, then the value should be an entity or ref to one // same is true of 'dataType' dataType if (this.DataTypeRef == null) { return(replacement); } CdmDataTypeDefinition dt = this.DataTypeRef.FetchObjectDefinition <CdmDataTypeDefinition>(resOpt); if (dt == null) { Logger.Error(ctx, Tag, nameof(ConstTypeCheck), this.AtCorpusPath, CdmLogCode.ErrUnrecognizedDataType, this.Name); return(null); } // compare with passed in value or default for parameter dynamic pValue = argumentValue; if (pValue == null) { pValue = this.DefaultValue; replacement = pValue; } if (pValue != null) { if (dt.IsDerivedFrom("cdmObject", resOpt)) { List <CdmObjectType> expectedTypes = new List <CdmObjectType>(); string expected = null; if (dt.IsDerivedFrom("entity", resOpt)) { expectedTypes.Add(CdmObjectType.ConstantEntityDef); expectedTypes.Add(CdmObjectType.EntityRef); expectedTypes.Add(CdmObjectType.EntityDef); expectedTypes.Add(CdmObjectType.ProjectionDef); expected = "entity"; } else if (dt.IsDerivedFrom("attribute", resOpt)) { expectedTypes.Add(CdmObjectType.AttributeRef); expectedTypes.Add(CdmObjectType.TypeAttributeDef); expectedTypes.Add(CdmObjectType.EntityAttributeDef); expected = "attribute"; } else if (dt.IsDerivedFrom("dataType", resOpt)) { expectedTypes.Add(CdmObjectType.DataTypeRef); expectedTypes.Add(CdmObjectType.DataTypeDef); expected = "dataType"; } else if (dt.IsDerivedFrom("purpose", resOpt)) { expectedTypes.Add(CdmObjectType.PurposeRef); expectedTypes.Add(CdmObjectType.PurposeDef); expected = "purpose"; } else if (dt.IsDerivedFrom("traitGroup", resOpt)) { expectedTypes.Add(CdmObjectType.TraitGroupRef); expectedTypes.Add(CdmObjectType.TraitGroupDef); expected = "traitGroup"; } else if (dt.IsDerivedFrom("trait", resOpt)) { expectedTypes.Add(CdmObjectType.TraitRef); expectedTypes.Add(CdmObjectType.TraitDef); expected = "trait"; } else if (dt.IsDerivedFrom("attributeGroup", resOpt)) { expectedTypes.Add(CdmObjectType.AttributeGroupRef); expectedTypes.Add(CdmObjectType.AttributeGroupDef); expected = "attributeGroup"; } if (expectedTypes.Count == 0) { Logger.Error(ctx, Tag, nameof(ConstTypeCheck), wrtDoc.FolderPath + wrtDoc.Name, CdmLogCode.ErrUnexpectedDataType, this.Name); } // if a string constant, resolve to an object ref. CdmObjectType foundType = CdmObjectType.Error; Type pValueType = pValue.GetType(); if (typeof(CdmObject).IsAssignableFrom(pValueType)) { foundType = (pValue as CdmObject).ObjectType; } string foundDesc = ctx.RelativePath; if (!(pValue is CdmObject)) { // pValue is a string or JValue pValue = (string)pValue; if (pValue == "this.attribute" && expected == "attribute") { // will get sorted out later when resolving traits foundType = CdmObjectType.AttributeRef; } else { foundDesc = pValue; int seekResAtt = CdmObjectReferenceBase.offsetAttributePromise(pValue); if (seekResAtt >= 0) { // get an object there that will get resolved later after resolved attributes replacement = new CdmAttributeReference(ctx, pValue, true); (replacement as CdmAttributeReference).Ctx = ctx; (replacement as CdmAttributeReference).InDocument = wrtDoc; foundType = CdmObjectType.AttributeRef; } else { CdmObjectBase lu = ctx.Corpus.ResolveSymbolReference(resOpt, wrtDoc, pValue, CdmObjectType.Error, retry: true); if (lu != null) { if (expected == "attribute") { replacement = new CdmAttributeReference(ctx, pValue, true); (replacement as CdmAttributeReference).Ctx = ctx; (replacement as CdmAttributeReference).InDocument = wrtDoc; foundType = CdmObjectType.AttributeRef; } else { replacement = lu; foundType = (replacement as CdmObject).ObjectType; } } } } } if (expectedTypes.IndexOf(foundType) == -1) { Logger.Error(ctx, Tag, nameof(ConstTypeCheck), wrtDoc.AtCorpusPath, CdmLogCode.ErrResolutionFailure, this.Name, expected, foundDesc, expected); } else { Logger.Info(ctx, Tag, nameof(ConstTypeCheck), wrtDoc.AtCorpusPath, $"resolved '{foundDesc}'"); } } } return(replacement); }
public override dynamic CopyData(ResolveOptions resOpt = null, CopyOptions options = null) { return(CdmObjectBase.CopyData <CdmOperationAlterTraits>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmConstantEntityDefinition>(this, resOpt, options)); }
public ResolvedEntityReferenceSet FetchResolvedEntityReferences(ResolveOptions resOpt = null) { bool wasPreviouslyResolving = this.Ctx.Corpus.isCurrentlyResolving; this.Ctx.Corpus.isCurrentlyResolving = true; if (resOpt == null) { resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives); } // this whole resolved entity ref goo will go away when resolved documents are done. // for now, it breaks if structured att sets get made. resOpt = CdmObjectBase.CopyResolveOptions(resOpt); resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet <string> { "normalized", "referenceOnly" }); ResolveContext ctx = this.Ctx as ResolveContext; // what it actually is ResolvedEntityReferenceSet entRefSetCache = ctx.FetchCache(this, resOpt, "entRefSet") as ResolvedEntityReferenceSet; if (entRefSetCache == null) { entRefSetCache = new ResolvedEntityReferenceSet(resOpt); if (resolvingEntityReferences == false) { resolvingEntityReferences = true; // get from dynamic base public class and then 'fix' those to point here instead. CdmObjectReference extRef = this.ExtendsEntityRef; if (extRef != null) { var extDef = extRef.FetchObjectDefinition <CdmEntityDefinition>(resOpt); if (extDef != null) { if (extDef == this) { extDef = extRef.FetchObjectDefinition <CdmEntityDefinition>(resOpt); } ResolvedEntityReferenceSet inherited = extDef.FetchResolvedEntityReferences(resOpt); if (inherited != null) { foreach (var res in inherited.Set) { ResolvedEntityReference resolvedEntityReference = res.Copy(); resolvedEntityReference.Referencing.Entity = this; entRefSetCache.Set.Add(resolvedEntityReference); } } } } if (this.Attributes != null) { for (int i = 0; i < this.Attributes.Count; i++) { // if dynamic refs come back from attributes, they don't know who we are, so they don't set the entity dynamic sub = this.Attributes.AllItems[i].FetchResolvedEntityReferences(resOpt); if (sub != null) { foreach (var res in sub.Set) { res.Referencing.Entity = this; } entRefSetCache.Add(sub); } } } ctx.UpdateCache(this, resOpt, "entRefSet", entRefSetCache); this.resolvingEntityReferences = false; } } this.Ctx.Corpus.isCurrentlyResolving = wasPreviouslyResolving; return(entRefSetCache); }
/// <summary> /// Creates a resolved copy of the entity. /// </summary> public async Task <CdmEntityDefinition> CreateResolvedEntityAsync(string newEntName, ResolveOptions resOpt = null, CdmFolderDefinition folder = null, string newDocName = null) { if (resOpt == null) { resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives); } if (resOpt.WrtDoc == null) { Logger.Error(nameof(CdmEntityDefinition), this.Ctx as ResolveContext, $"No WRT document was supplied.", nameof(CreateResolvedEntityAsync)); return(null); } if (string.IsNullOrEmpty(newEntName)) { Logger.Error(nameof(CdmEntityDefinition), this.Ctx as ResolveContext, $"No Entity Name provided.", nameof(CreateResolvedEntityAsync)); return(null); } // if the wrtDoc needs to be indexed (like it was just modified) then do that first if (!await resOpt.WrtDoc.IndexIfNeeded(resOpt, true)) { Logger.Error(nameof(CdmEntityDefinition), this.Ctx as ResolveContext, $"Couldn't index source document.", nameof(CreateResolvedEntityAsync)); return(null); } if (folder == null) { folder = this.InDocument.Folder; } string fileName = (string.IsNullOrEmpty(newDocName)) ? $"{newEntName}.cdm.json" : newDocName; string origDoc = this.InDocument.AtCorpusPath; // Don't overwite the source document string targetAtCorpusPath = $"{this.Ctx.Corpus.Storage.CreateAbsoluteCorpusPath(folder.AtCorpusPath, folder)}{fileName}"; if (StringUtils.EqualsWithIgnoreCase(targetAtCorpusPath, origDoc)) { Logger.Error(nameof(CdmEntityDefinition), this.Ctx as ResolveContext, $"Attempting to replace source entity's document '{targetAtCorpusPath}'", nameof(CreateResolvedEntityAsync)); return(null); } // make the top level attribute context for this entity // for this whole section where we generate the attribute context tree and get resolved attributes // set the flag that keeps all of the parent changes and document dirty from from happening bool wasResolving = this.Ctx.Corpus.isCurrentlyResolving; this.Ctx.Corpus.isCurrentlyResolving = true; string entName = newEntName; ResolveContext ctx = this.Ctx as ResolveContext; CdmAttributeContext attCtxEnt = ctx.Corpus.MakeObject <CdmAttributeContext>(CdmObjectType.AttributeContextDef, entName, true); attCtxEnt.Ctx = ctx; attCtxEnt.InDocument = this.InDocument; // cheating a bit to put the paths in the right place AttributeContextParameters acp = new AttributeContextParameters { under = attCtxEnt, type = CdmAttributeContextType.AttributeGroup, Name = "attributeContext" }; CdmAttributeContext attCtxAC = CdmAttributeContext.CreateChildUnder(resOpt, acp); AttributeContextParameters acpEnt = new AttributeContextParameters { under = attCtxAC, type = CdmAttributeContextType.Entity, Name = entName, Regarding = ctx.Corpus.MakeObject <CdmObject>(CdmObjectType.EntityRef, this.GetName(), true) }; // use this whenever we need to keep references pointing at things that were already found. used when 'fixing' references by localizing to a new document ResolveOptions resOptCopy = CdmObjectBase.CopyResolveOptions(resOpt); resOptCopy.SaveResolutionsOnCopy = true; // resolve attributes with this context. the end result is that each resolved attribute // points to the level of the context where it was created var ras = this.FetchResolvedAttributes(resOptCopy, acpEnt); if (ras == null) { this.resolvingAttributes = false; return(null); } // create a new copy of the attribute context for this entity HashSet <CdmAttributeContext> allAttCtx = new HashSet <CdmAttributeContext>(); CdmAttributeContext newNode = attCtxEnt.CopyNode(resOpt) as CdmAttributeContext; attCtxEnt = attCtxEnt.CopyAttributeContextTree(resOpt, newNode, ras, allAttCtx, "resolvedFrom"); CdmAttributeContext attCtx = (attCtxEnt.Contents[0] as CdmAttributeContext).Contents[0] as CdmAttributeContext; this.Ctx.Corpus.isCurrentlyResolving = wasResolving; // make a new document in given folder if provided or the same folder as the source entity folder.Documents.Remove(fileName); CdmDocumentDefinition docRes = folder.Documents.Add(fileName); // add a import of the source document origDoc = this.Ctx.Corpus.Storage.CreateRelativeCorpusPath(origDoc, docRes); // just in case we missed the prefix docRes.Imports.Add(origDoc, "resolvedFrom"); // make the empty entity CdmEntityDefinition entResolved = docRes.Definitions.Add(entName); // set the context to the copy of the tree. fix the docs on the context nodes entResolved.AttributeContext = attCtx; attCtx.Visit($"{entName}/attributeContext/", new VisitCallback { Invoke = (obj, path) => { obj.InDocument = docRes; return(false); } }, null); // add the traits of the entity ResolvedTraitSet rtsEnt = this.FetchResolvedTraits(resOpt); rtsEnt.Set.ForEach(rt => { var traitRef = CdmObjectBase.ResolvedTraitToTraitRef(resOptCopy, rt); (entResolved as CdmObjectDefinition).ExhibitsTraits.Add(traitRef); }); // the attributes have been named, shaped, etc for this entity so now it is safe to go and // make each attribute context level point at these final versions of attributes IDictionary <string, int> attPath2Order = new Dictionary <string, int>(); Action <ResolvedAttributeSet, string> pointContextAtResolvedAtts = null; pointContextAtResolvedAtts = (rasSub, path) => { rasSub.Set.ForEach(ra => { List <CdmAttributeContext> raCtxInEnt = new List <CdmAttributeContext>(); HashSet <CdmAttributeContext> raCtxSet = null; rasSub.Ra2attCtxSet.TryGetValue(ra, out raCtxSet); // find the correct attCtx for this copy, intersect these two sets // (iterate over the shortest list) if (allAttCtx.Count < raCtxSet.Count) { foreach (CdmAttributeContext currAttCtx in allAttCtx) { if (raCtxSet.Contains(currAttCtx)) { raCtxInEnt.Add(currAttCtx); } } } else { foreach (CdmAttributeContext currAttCtx in raCtxSet) { if (allAttCtx.Contains(currAttCtx)) { raCtxInEnt.Add(currAttCtx); } } } foreach (CdmAttributeContext raCtx in raCtxInEnt) { var refs = raCtx.Contents; // there might be more than one explanation for where and attribute came from when things get merges as they do // this won't work when I add the structured attributes to avoid name collisions string attRefPath = path + ra.ResolvedName; if ((ra.Target as CdmAttribute)?.GetType().GetMethod("GetObjectType") != null) { if (!attPath2Order.ContainsKey(attRefPath)) { var attRef = this.Ctx.Corpus.MakeObject <CdmObjectReferenceBase>(CdmObjectType.AttributeRef, attRefPath, true); // only need one explanation for this path to the insert order attPath2Order.Add(attRef.NamedReference, ra.InsertOrder); refs.Add(attRef); } } else { attRefPath += "/members/"; pointContextAtResolvedAtts(ra.Target as ResolvedAttributeSet, attRefPath); } } }); }; pointContextAtResolvedAtts(ras, entName + "/hasAttributes/"); // generated attribute structures may end up with 0 attributes after that. prune them Func <CdmObject, bool, bool> CleanSubGroup = null; CleanSubGroup = (subItem, underGenerated) => { if (subItem.ObjectType == CdmObjectType.AttributeRef) { return(true); // not empty } CdmAttributeContext ac = subItem as CdmAttributeContext; if (ac.Type == CdmAttributeContextType.GeneratedSet) { underGenerated = true; } if (ac.Contents == null || ac.Contents.Count == 0) { return(false); // empty } // look at all children, make a set to remove List <CdmAttributeContext> toRemove = new List <CdmAttributeContext>(); foreach (var subSub in ac.Contents) { if (CleanSubGroup(subSub, underGenerated) == false) { bool potentialTarget = underGenerated; if (potentialTarget == false) { // cast is safe because we returned false meaning empty and not a attribute ref // so is this the set holder itself? potentialTarget = (subSub as CdmAttributeContext).Type == CdmAttributeContextType.GeneratedSet; } if (potentialTarget) { toRemove.Add(subSub as CdmAttributeContext); } } } foreach (var toDie in toRemove) { ac.Contents.Remove(toDie); } return(ac.Contents.Count != 0); }; CleanSubGroup(attCtx, false); Func <CdmAttributeContext, int?> orderContents = null; // create an all-up ordering of attributes at the leaves of this tree based on insert order // sort the attributes in each context by their creation order and mix that with the other sub-contexts that have been sorted Func <CdmObject, int?> getOrderNum = (item) => { if (item.ObjectType == CdmObjectType.AttributeContextDef && orderContents != null) { return(orderContents(item as CdmAttributeContext)); } else if (item.ObjectType == CdmObjectType.AttributeRef) { string attName = (item as CdmAttributeReference).NamedReference; int o = attPath2Order[attName]; return(o); } else { return(-1); // put the mystery item on top. } }; orderContents = (CdmAttributeContext under) => { if (under.LowestOrder == null) { under.LowestOrder = -1; // used for group with nothing but traits if (under.Contents.Count == 1) { under.LowestOrder = getOrderNum(under.Contents[0]); } else { under.Contents.AllItems.Sort((l, r) => { int lNum = -1; int rNum = -1; int?aux; aux = getOrderNum(l); if (aux != null) { lNum = (int)aux; } aux = getOrderNum(r); if (aux != null) { rNum = (int)aux; } if (lNum != -1 && (under.LowestOrder == -1 || lNum < under.LowestOrder)) { under.LowestOrder = lNum; } if (rNum != -1 && (under.LowestOrder == -1 || rNum < under.LowestOrder)) { under.LowestOrder = rNum; } return(lNum - rNum); }); } } return(under.LowestOrder); }; orderContents((CdmAttributeContext)attCtx); // resolved attributes can gain traits that are applied to an entity when referenced // since these traits are described in the context, it is redundant and messy to list them in the attribute // so, remove them. create and cache a set of names to look for per context // there is actually a hierarchy to all attributes from the base entity should have all traits applied independently of the // sub-context they come from. Same is true of attribute entities. so do this recursively top down var ctx2traitNames = new Dictionary <CdmAttributeContext, HashSet <string> >(); Action <CdmAttributeContext, HashSet <string> > collectContextTraits = null; collectContextTraits = (subAttCtx, inheritedTraitNames) => { var traitNamesHere = new HashSet <string>(inheritedTraitNames); var traitsHere = subAttCtx.ExhibitsTraits; if (traitsHere != null) { foreach (var tat in traitsHere) { traitNamesHere.Add(tat.NamedReference); } } ctx2traitNames.Add(subAttCtx, traitNamesHere); subAttCtx.Contents.AllItems.ForEach((cr) => { if (cr.ObjectType == CdmObjectType.AttributeContextDef) { // do this for all types? collectContextTraits(cr as CdmAttributeContext, traitNamesHere); } }); }; collectContextTraits(attCtx, new HashSet <string>()); // add the attributes, put them in attribute groups if structure needed IDictionary <ResolvedAttribute, string> resAtt2RefPath = new Dictionary <ResolvedAttribute, string>(); Action <ResolvedAttributeSet, dynamic, string> addAttributes = null; addAttributes = (rasSub, container, path) => { rasSub.Set.ForEach(ra => { string attPath = path + ra.ResolvedName; // use the path of the context associated with this attribute to find the new context that matches on path HashSet <CdmAttributeContext> raCtxSet = null; rasSub.Ra2attCtxSet.TryGetValue(ra, out raCtxSet); CdmAttributeContext raCtx = null; // find the correct attCtx for this copy // (interate over the shortest list) if (allAttCtx.Count < raCtxSet.Count) { foreach (CdmAttributeContext currAttCtx in allAttCtx) { if (raCtxSet.Contains(currAttCtx)) { raCtx = currAttCtx; break; } } } else { foreach (CdmAttributeContext currAttCtx in raCtxSet) { if (allAttCtx.Contains(currAttCtx)) { raCtx = currAttCtx; break; } } } if (ra.Target is ResolvedAttributeSet) { // this is a set of attributes. // make an attribute group to hold them CdmAttributeGroupDefinition attGrp = this.Ctx.Corpus.MakeObject <CdmAttributeGroupDefinition>(CdmObjectType.AttributeGroupDef, ra.ResolvedName, false); attGrp.AttributeContext = this.Ctx.Corpus.MakeObject <CdmAttributeContextReference>(CdmObjectType.AttributeContextRef, raCtx.AtCorpusPath, true); // take any traits from the set and make them look like traits exhibited by the group HashSet <string> avoidSet = ctx2traitNames[raCtx]; ResolvedTraitSet rtsAtt = ra.ResolvedTraits; rtsAtt.Set.ForEach(rt => { if (rt.Trait.Ugly != true) { // don't mention your ugly traits if (avoidSet?.Contains(rt.TraitName) != true) { // avoid the ones from the context var traitRef = CdmObjectBase.ResolvedTraitToTraitRef(resOptCopy, rt); (attGrp as CdmObjectDefinitionBase).ExhibitsTraits.Add(traitRef); } } }); // wrap it in a reference and then recurse with this as the new container CdmAttributeGroupReference attGrpRef = this.Ctx.Corpus.MakeObject <CdmAttributeGroupReference>(CdmObjectType.AttributeGroupRef, null, false); attGrpRef.ExplicitReference = attGrp; container.AddAttributeDef(attGrpRef); // isn't this where ... addAttributes(ra.Target as ResolvedAttributeSet, attGrp, attPath + "/members/"); } else { CdmTypeAttributeDefinition att = this.Ctx.Corpus.MakeObject <CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, ra.ResolvedName, false); att.AttributeContext = this.Ctx.Corpus.MakeObject <CdmAttributeContextReference>(CdmObjectType.AttributeContextRef, raCtx.AtCorpusPath, true); HashSet <string> avoidSet = ctx2traitNames[raCtx]; ResolvedTraitSet rtsAtt = ra.ResolvedTraits; rtsAtt.Set.ForEach(rt => { if (rt.Trait.Ugly != true) { // don't mention your ugly traits if (avoidSet?.Contains(rt.TraitName) != true) { // avoid the ones from the context var traitRef = CdmObjectBase.ResolvedTraitToTraitRef(resOptCopy, rt); ((CdmTypeAttributeDefinition)att).AppliedTraits.Add(traitRef); } } }); // none of the dataformat traits have the bit set that will make them turn into a property // this is intentional so that the format traits make it into the resolved object // but, we still want a guess as the data format, so get it and set it. var impliedDataFormat = att.DataFormat; if (impliedDataFormat != CdmDataFormat.Unknown) { att.DataFormat = impliedDataFormat; } container.AddAttributeDef(att); resAtt2RefPath[ra] = attPath; } }); }; addAttributes(ras, entResolved, entName + "/hasAttributes/"); // any resolved traits that hold arguments with attribute refs should get 'fixed' here Action <CdmTraitReference, string, bool> replaceTraitAttRef = (tr, entityHint, isAttributeContext) => { if (tr.Arguments != null) { foreach (CdmArgumentDefinition arg in tr.Arguments.AllItems) { dynamic v = arg.UnResolvedValue != null ? arg.UnResolvedValue : arg.Value; // is this an attribute reference? if (v != null && (v as CdmObject)?.ObjectType == CdmObjectType.AttributeRef) { // only try this if the reference has no path to it (only happens with intra-entity att refs) var attRef = v as CdmAttributeReference; if (!string.IsNullOrEmpty(attRef.NamedReference) && attRef.NamedReference.IndexOf('/') == -1) { if (arg.UnResolvedValue == null) { arg.UnResolvedValue = arg.Value; } // give a promise that can be worked out later. assumption is that the attribute must come from this entity. var newAttRef = this.Ctx.Corpus.MakeRef <CdmAttributeReference>(CdmObjectType.AttributeRef, entityHint + "/(resolvedAttributes)/" + attRef.NamedReference, true); // inDocument is not propagated during resolution, so set it here newAttRef.InDocument = arg.InDocument; arg.Value = newAttRef; } } } } }; // fix entity traits if (entResolved.ExhibitsTraits != null) { foreach (var et in entResolved.ExhibitsTraits) { replaceTraitAttRef(et, newEntName, false); } } // fix context traits Action <CdmAttributeContext, string> fixContextTraits = null; fixContextTraits = (subAttCtx, entityHint) => { var traitsHere = subAttCtx.ExhibitsTraits; if (traitsHere != null) { foreach (var tr in traitsHere) { replaceTraitAttRef(tr, entityHint, true); } } subAttCtx.Contents.AllItems.ForEach((cr) => { if (cr.ObjectType == CdmObjectType.AttributeContextDef) { // if this is a new entity context, get the name to pass along CdmAttributeContext subSubAttCtx = (CdmAttributeContext)cr; string subEntityHint = entityHint; if (subSubAttCtx.Type == CdmAttributeContextType.Entity) { subEntityHint = subSubAttCtx.Definition.NamedReference; } // do this for all types fixContextTraits(subSubAttCtx, subEntityHint); } }); }; fixContextTraits(attCtx, newEntName); // and the attribute traits var entAttributes = entResolved.Attributes; if (entAttributes != null) { foreach (var entAtt in entAttributes) { CdmTraitCollection attTraits = entAtt.AppliedTraits; if (attTraits != null) { foreach (var tr in attTraits) { replaceTraitAttRef(tr, newEntName, false); } } } } // we are about to put this content created in the context of various documents (like references to attributes from base entities, etc.) // into one specific document. all of the borrowed refs need to work. so, re-write all string references to work from this new document // the catch-22 is that the new document needs these fixes done before it can be used to make these fixes. // the fix needs to happen in the middle of the refresh // trigger the document to refresh current content into the resolved OM attCtx.Parent = null; // remove the fake parent that made the paths work ResolveOptions resOptNew = CdmObjectBase.CopyResolveOptions(resOpt); resOptNew.LocalizeReferencesFor = docRes; resOptNew.WrtDoc = docRes; if (!await docRes.RefreshAsync(resOptNew)) { Logger.Error(nameof(CdmEntityDefinition), this.Ctx as ResolveContext, $"Failed to index the resolved document.", nameof(CreateResolvedEntityAsync)); return(null); } // get a fresh ref entResolved = docRes.FetchObjectFromDocumentPath(entName, resOptNew) as CdmEntityDefinition; this.Ctx.Corpus.resEntMap[this.AtCorpusPath] = entResolved.AtCorpusPath; return(entResolved); }
internal static CdmAttributeContext CreateChildUnder(ResolveOptions resOpt, AttributeContextParameters acp) { if (acp == null) { return(null); } if (acp.type == CdmAttributeContextType.PassThrough) { return(acp.under as CdmAttributeContext); } // this flag makes sure we hold on to any resolved object refs when things get copied ResolveOptions resOptCopy = resOpt.Copy(); resOptCopy.SaveResolutionsOnCopy = true; CdmObjectReference definition = null; ResolvedTraitSet rtsApplied = null; // get a simple reference to definition object to avoid getting the traits that might be part of this ref // included in the link to the definition. if (acp.Regarding != null) { // make a portable reference. this MUST be fixed up when the context node lands in the final document definition = (acp.Regarding as CdmObjectBase).CreatePortableReference(resOptCopy); // now get the traits applied at this reference (applied only, not the ones that are part of the definition of the object) // and make them the traits for this context if (acp.IncludeTraits) { rtsApplied = (acp.Regarding as CdmObjectBase).FetchResolvedTraits(resOptCopy); } } CdmAttributeContext underChild = acp.under.Ctx.Corpus.MakeObject <CdmAttributeContext>(CdmObjectType.AttributeContextDef, acp.Name); // need context to make this a 'live' object underChild.Ctx = acp.under.Ctx; underChild.InDocument = (acp.under as CdmAttributeContext).InDocument; underChild.Type = acp.type; underChild.Definition = definition; // add traits if there are any if (rtsApplied?.Set != null) { rtsApplied.Set.ForEach(rt => { var traitRef = CdmObjectBase.ResolvedTraitToTraitRef(resOptCopy, rt); underChild.ExhibitsTraits.Add(traitRef); }); } // add to parent underChild.SetParent(resOptCopy, acp.under as CdmAttributeContext); if (resOptCopy.MapOldCtxToNewCtx != null) { resOptCopy.MapOldCtxToNewCtx[underChild] = underChild; // so we can find every node, not only the replaced ones } return(underChild); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmParameterDefinition>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return CdmObjectBase.CopyData<CdmAttributeContextReference>(this, resOpt, options); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmTraitReference>(this, resOpt, options)); }
public static CdmManifestDeclarationDefinition InstanceFromData(CdmCorpusContext ctx, ManifestDeclaration obj) { return(CdmObjectBase.InstanceFromData <CdmManifestDeclarationDefinition, ManifestDeclaration>(ctx, obj)); }
public static CdmDocumentDefinition InstanceFromData(CdmCorpusContext ctx, dynamic obj) { return(CdmObjectBase.InstanceFromData <CdmDocumentDefinition, DocumentContent>(ctx, obj)); }
public static CdmFolderDefinition InstanceFromData(CdmCorpusContext ctx, Folder obj) { return(CdmObjectBase.InstanceFromData <CdmFolderDefinition, Folder>(ctx, obj)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmImport>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt, CopyOptions options) { return(CdmObjectBase.CopyData <CdmAttributeResolutionGuidance>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt = null, CopyOptions options = null) { return(CdmObjectBase.CopyData <CdmOperationCombineAttributes>(this, resOpt, options)); }
public override dynamic CopyData(ResolveOptions resOpt = null, CopyOptions options = null) { return(CdmObjectBase.CopyData <CdmOperationReplaceAsForeignKey>(this, resOpt, options)); }