public CdmObjectBase resolveSymbolReference()

in objectModel/Java/objectmodel/src/main/java/com/microsoft/commondatamodel/objectmodel/cdm/CdmCorpusDefinition.java [765:1024]


  public CdmObjectBase resolveSymbolReference(
      final ResolveOptions resOpt,
      final CdmDocumentDefinition fromDoc,
      String symbolDef,
      final CdmObjectType expectedType,
      final boolean retry) {
    final ResolveContext ctx = (ResolveContext) this.ctx;

    // Given a symbolic name, find the 'highest priority' definition of the object from the point
    // of view of a given document (with respect to, wrtDoc) (meaning given a document and the
    // things it defines and the files it imports and the files they import, where is the 'last'
    // definition found).
    if (resOpt == null || resOpt.getWrtDoc() == null || symbolDef == null) {
      // No way to figure this out.
      return null;
    }

    CdmDocumentDefinition wrtDoc = resOpt.getWrtDoc();

    if (wrtDoc.getNeedsIndexing() && !wrtDoc.isCurrentlyIndexing()) {
      if (!wrtDoc.indexIfNeededAsync(resOpt, true).join()) {
        Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrIndexFailed);
        return null;
      }
    }

    if (wrtDoc.getNeedsIndexing() && resOpt.getImportsLoadStrategy() == ImportsLoadStrategy.DoNotLoad) {
      Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrSymbolNotFound, symbolDef, "because the ImportsLoadStrategy is set to DoNotLoad");
      return null;
    }

    // save the symbol name as it got here
    String initialSymbol = symbolDef;

    // when trying to find a reference, first find the definition that contains it
    // and then look for the reference inside it.
    boolean isReference = symbolDef != null && symbolDef.endsWith("(ref)");
    if (isReference) {
      int defIndex = symbolDef.indexOf("/");
      symbolDef = symbolDef.substring(0, defIndex);
    }

    // Get the array of documents where the symbol is defined.
    final DocsResult symbolDocsResult = this.docsForSymbol(resOpt, wrtDoc, fromDoc, symbolDef);

    CdmDocumentDefinition docBest = symbolDocsResult.getDocBest();
    symbolDef = symbolDocsResult.getNewSymbol();

    if (!isReference) {
      initialSymbol = symbolDef;
    }

    final List<CdmDocumentDefinition> docs = symbolDocsResult.getDocList();
    if (null != docs) {
      // Add this symbol to the set being collected in resOpt, we will need this when caching.
      if (null == resOpt.getSymbolRefSet()) {
        resOpt.setSymbolRefSet(new SymbolSet());
      }

      resOpt.getSymbolRefSet().add(symbolDef);

      // For the given doc, there is a sorted list of imported docs (including the doc
      // itself as item 0). Find the lowest number imported document that has a definition
      // for this symbol.
      if (null == wrtDoc.getImportPriorities()) {
        return null;
      }

      final Map<CdmDocumentDefinition, ImportInfo> importPriority = wrtDoc.getImportPriorities().getImportPriority();

      if (importPriority.size() == 0) {
        return null;
      }

      if (null == docBest) {
        docBest = CdmCorpusDefinition.fetchPriorityDocument(docs, importPriority);
      }
    }

    // Perhaps we have never heard of this symbol in the imports for this document?
    if (null == docBest) {
      return null;
    }

    // Return the definition found in the best document
    CdmObjectBase found = docBest.internalDeclarations.get(symbolDef);

    // in case we are trying to find a reference, the object we found previously is the definition that contains the reference.
    // look inside the definition now.
    if (found != null && isReference) {
      AtomicReference<CdmObjectBase> foundRef = new AtomicReference<>();
      // try to find the reference
      final String symbol = initialSymbol;
      found.visit("", (obj, objPath) -> {
          if (symbol.equals(objPath)) {
            foundRef.set((CdmObjectBase) obj);
            return true;
          }
          return false;
        }, null);
      found = foundRef.get();
    }

    if (found == null && retry) {
      // Maybe just locatable from here not defined here.
      // This happens when the symbol is monikered, but the moniker path doesn't lead to the document where the symbol is defined.
      // It leads to the document from where the symbol can be found. 
      // Ex.: resolvedFrom/Owner, while resolvedFrom is the Account that imports Owner.
      found = this.resolveSymbolReference(resOpt, docBest, initialSymbol, expectedType, false);
    }

    if (found != null && expectedType != CdmObjectType.Error) {
      switch (expectedType) {
        case TraitRef: {
          if (found.getObjectType() != CdmObjectType.TraitDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "trait", symbolDef);
            found = null;
          }
          break;
        }
        case DataTypeRef: {
          if (found.getObjectType() != CdmObjectType.DataTypeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "dataType", symbolDef);
            found = null;
          }
          break;
        }
        case EntityRef: {
          if (found.getObjectType() != CdmObjectType.EntityDef && found.getObjectType() != CdmObjectType.ProjectionDef && found.getObjectType() != CdmObjectType.ConstantEntityDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "entity or type projection or type constant entity", symbolDef);
            found = null;
          }
          break;
        }
        case ParameterDef: {
          if (found.getObjectType() != CdmObjectType.ParameterDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "parameter", symbolDef);
            found = null;
          }
          break;
        }
        case PurposeRef: {
          if (found.getObjectType() != CdmObjectType.PurposeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "purpose", symbolDef);
            found = null;
          }
          break;
        }
        case TraitGroupRef:
          if (found.getObjectType() != CdmObjectType.TraitGroupDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "traitGroup", symbolDef);
            found = null;
          }
          break;
        case AttributeGroupRef: {
          if (found.getObjectType() != CdmObjectType.AttributeGroupDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "attributeGroup", symbolDef);
            found = null;
          }
          break;
        }
        case ProjectionDef: {
          if (found.getObjectType() != CdmObjectType.ProjectionDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "add count attribute operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAddCountAttributeDef: {
          if (found.getObjectType() != CdmObjectType.OperationAddCountAttributeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "add supporting attribute operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAddSupportingAttributeDef: {
          if (found.getObjectType() != CdmObjectType.OperationAddSupportingAttributeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "type attribute operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAddTypeAttributeDef: {
          if (found.getObjectType() != CdmObjectType.OperationAddTypeAttributeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "attribute operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationExcludeAttributesDef: {
          if (found.getObjectType() != CdmObjectType.OperationExcludeAttributesDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "exclude attributes operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationArrayExpansionDef: {
          if (found.getObjectType() != CdmObjectType.OperationArrayExpansionDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "array expansion operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationCombineAttributesDef: {
          if (found.getObjectType() != CdmObjectType.OperationCombineAttributesDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "combine attributes operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationRenameAttributesDef: {
          if (found.getObjectType() != CdmObjectType.OperationRenameAttributesDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "rename attributes operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationReplaceAsForeignKeyDef: {
          if (found.getObjectType() != CdmObjectType.OperationReplaceAsForeignKeyDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "replace as foreign key operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationIncludeAttributesDef: {
          if (found.getObjectType() != CdmObjectType.OperationIncludeAttributesDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "include attributes operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAddAttributeGroupDef: {
          if (found.getObjectType() != CdmObjectType.OperationAddAttributeGroupDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "add attribute group operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAlterTraitsDef: {
          if (found.getObjectType() != CdmObjectType.OperationAlterTraitsDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "alter traits operation", symbolDef);
            found = null;
          }
          break;
        }
        case OperationAddArtifactAttributeDef: {
          if (found.getObjectType() != CdmObjectType.OperationAddArtifactAttributeDef) {
            Logger.error(ctx, TAG, "resolveSymbolReference", wrtDoc.getAtCorpusPath(), CdmLogCode.ErrUnexpectedType, "add artifact attribute operation", symbolDef);
            found = null;
          }
          break;
        }
        default: {
          break;
        }
      }
    }

    return found;
  }