/// <inheritdoc /> public override CdmObjectReference CreateSimpleReference(ResolveOptions resOpt = null) { if (resOpt == null) { resOpt = new ResolveOptions(this, this.Ctx.Corpus.DefaultResolutionDirectives); } string name; if (!string.IsNullOrEmpty(this.DeclaredPath)) { name = this.DeclaredPath; } else { name = this.GetName(); } CdmObjectReferenceBase cdmObjectRef = this.Ctx.Corpus.MakeObject <CdmObjectReferenceBase>(CdmCorpusDefinition.MapReferenceType(this.ObjectType), name, true) as CdmObjectReferenceBase; if (resOpt.SaveResolutionsOnCopy) { // used to localize references between documents cdmObjectRef.ExplicitReference = this; cdmObjectRef.InDocument = this.InDocument; } return(cdmObjectRef); }
/// Creates a 'portable' reference object to this object. portable means there is no symbolic name set until this reference is placed /// into some final document. internal override CdmObjectReference CreatePortableReference(ResolveOptions resOpt) { CdmObjectReferenceBase cdmObjectRef = this.Ctx.Corpus.MakeObject <CdmObjectReferenceBase>(CdmCorpusDefinition.MapReferenceType(this.ObjectType), "portable", true) as CdmObjectReferenceBase; cdmObjectRef.ExplicitReference = this; cdmObjectRef.InDocument = this.InDocument; // where it started life return(cdmObjectRef); }
/// <summary> /// Fetches the corresponding object definition for every object reference. /// </summary> /// <param name="objects"></param> /// <param name="resOpt"></param> internal void ResolveObjectDefinitions(ResolveOptions resOpt) { ResolveContext ctx = this.Ctx as ResolveContext; resOpt.IndexingDoc = this; foreach (var obj in this.InternalObjects) { switch (obj.ObjectType) { case CdmObjectType.AttributeRef: case CdmObjectType.AttributeGroupRef: case CdmObjectType.AttributeContextRef: case CdmObjectType.DataTypeRef: case CdmObjectType.EntityRef: case CdmObjectType.PurposeRef: case CdmObjectType.TraitRef: ctx.RelativePath = obj.DeclaredPath; CdmObjectReferenceBase reff = obj as CdmObjectReferenceBase; if (CdmObjectReferenceBase.offsetAttributePromise(reff.NamedReference) < 0) { CdmObjectDefinition resNew = reff.FetchObjectDefinition <CdmObjectDefinition>(resOpt); if (resNew == null) { // It's okay if references can't be resolved when shallow validation is enabled. if (resOpt.ShallowValidation) { Logger.Warning(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, CdmLogCode.WarnResolveReferenceFailure, reff.NamedReference); } else { Logger.Error(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, CdmLogCode.ErrResolveReferenceFailure, reff.NamedReference); // don't check in this file without both of these comments. handy for debug of failed lookups // CdmObjectDefinitionBase resTest = ref.FetchObjectDefinition(resOpt); } } else { Logger.Info(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, $"resolved '{reff.NamedReference}'"); } } break; case CdmObjectType.ParameterDef: // when a parameter has a datatype that is a cdm object, validate that any default value is the // right kind object CdmParameterDefinition parameter = obj as CdmParameterDefinition; parameter.ConstTypeCheck(resOpt, this, null); break; } } resOpt.IndexingDoc = null; }
internal CdmObject FetchObjectFromDocumentPath(string objectPath, ResolveOptions resOpt) { // in current document? if (this.InternalDeclarations.ContainsKey(objectPath)) { return(this.InternalDeclarations[objectPath]); } else { // this might be a request for an object def drill through of a reference. // path/(object)/paths // there can be several such requests in one path AND some of the requested // defintions might be defined inline inside a reference meaning the declared path // includes that reference name and could still be inside this document. example: // /path/path/refToInline/(object)/member1/refToSymbol/(object)/member2 // the full path is not in this doc but /path/path/refToInline/(object)/member1/refToSymbol // is declared in this document. we then need to go to the doc for refToSymbol and // search for refToSymbol/member2 // work backward until we find something in this document int lastObj = objectPath.LastIndexOf("/(object)"); string thisDocPart = objectPath; while (lastObj > 0) { thisDocPart = objectPath.Substring(0, lastObj); if (this.InternalDeclarations.ContainsKey(thisDocPart)) { CdmObjectReferenceBase thisDocObjRef = this.InternalDeclarations[thisDocPart] as CdmObjectReferenceBase; CdmObjectDefinitionBase thatDocObjDef = thisDocObjRef.FetchObjectDefinition <CdmObjectDefinitionBase>(resOpt); if (thatDocObjDef != null) { // get from other document. // but first fix the path to look like it is relative to that object as declared in that doc string thatDocPart = objectPath.Substring(lastObj + "/(object)".Length); thatDocPart = $"{thatDocObjDef.DeclaredPath}{thatDocPart}"; if (thatDocPart == objectPath) { // we got back to were we started. probably because something is just not found. return(null); } return(thatDocObjDef.InDocument.FetchObjectFromDocumentPath(thatDocPart, resOpt)); } return(null); } lastObj = thisDocPart.LastIndexOf("/(object)"); } } return(null); }
/// Creates a 'portable' reference object to this object. portable means there is no symbolic name set until this reference is placed /// into some final document. internal override CdmObjectReference CreatePortableReference(ResolveOptions resOpt) { CdmObjectReferenceBase cdmObjectRef = this.Ctx.Corpus.MakeObject <CdmObjectReferenceBase>(CdmCorpusDefinition.MapReferenceType(this.ObjectType), "portable", true) as CdmObjectReferenceBase; cdmObjectRef.ExplicitReference = this.FetchObjectDefinition <CdmObjectDefinition>(resOpt); if (cdmObjectRef.ExplicitReference == null || (cdmObjectRef.InDocument == null && this.InDocument == null)) { return(null); // not allowed } if (cdmObjectRef.InDocument == null) { cdmObjectRef.InDocument = this.InDocument; // if the object has no document, take from the reference } return(cdmObjectRef); }
internal void SetParent(ResolveOptions resOpt, CdmAttributeContext parent) { // will need a working reference to this as the parent CdmObjectReferenceBase parentRef = this.Ctx.Corpus.MakeObject <CdmObjectReferenceBase>(CdmObjectType.AttributeContextRef, parent.AtCorpusPath, true); if (this.Name != null) { this.AtCorpusPath = parent.AtCorpusPath + "/" + this.Name; } parentRef.ExplicitReference = parent; // setting this will let the 'localize references' code trace from any document back to where the parent is defined parentRef.DocCreatedIn = parent.DocCreatedIn; CdmCollection <CdmObject> parentContents = parent.Contents; parentContents.Add(this); this.Parent = parentRef; }
internal override CdmObjectReferenceBase CopyRefObject(ResolveOptions resOpt, dynamic refTo, bool simpleReference, CdmObjectReferenceBase host = null) { CdmTraitReference copy; if (host == null) { copy = new CdmTraitReference(this.Ctx, refTo, simpleReference, this.Arguments?.Count > 0); } else { copy = host.CopyToHost(this.Ctx, refTo, simpleReference); copy.Arguments.Clear(); } if (!simpleReference) { copy.ResolvedArguments = this.ResolvedArguments; } foreach (var arg in this.Arguments) { copy.Arguments.Add(arg); } return(copy); }
internal override CdmObjectReferenceBase CopyRefObject(ResolveOptions resOpt, dynamic refTo, bool simpleReference, CdmObjectReferenceBase host = null) { if (host == null) { return(new CdmAttributeGroupReference(this.Ctx, refTo, simpleReference)); } else { return(host.CopyToHost(this.Ctx, refTo, simpleReference)); } }
internal override CdmObjectReferenceBase CopyRefObject(ResolveOptions resOpt, dynamic refTo, bool simpleReference, CdmObjectReferenceBase host = null) { if (host == null) { // for inline attribute group definition, the owner information is lost here when a ref object created // updating it here if (this.ExplicitReference != null && this.ExplicitReference.ObjectType == CdmObjectType.AttributeGroupDef && this.ExplicitReference.Owner == null) { this.ExplicitReference.Owner = this.Owner; } return(new CdmAttributeGroupReference(this.Ctx, refTo, simpleReference)); } else { return(host.CopyToHost(this.Ctx, refTo, simpleReference)); } }
internal abstract CdmObjectReferenceBase CopyRefObject(ResolveOptions resOpt, dynamic refTo, bool simpleReference, CdmObjectReferenceBase host = null);
/// <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); }