public ProjectModelFetcher(NbGradleProject project, GradleTarget gradleTarget) {
      this.settingsFile =
          NbGenericModelInfo.findSettingsGradle(project.getProjectDirectoryAsFile());

      List<NbGradleExtensionRef> extensions = project.getExtensionRefs();
      this.toolingModelNeeds = CollectionUtils.newHashMap(extensions.size());

      Map<Object, List<GradleBuildInfoQuery<?>>> buildInfoRequests = Collections.emptyMap();

      Map<Object, List<GradleProjectInfoQuery<?>>> projectInfoRequests = new HashMap<>();

      List<Class<?>> models = new LinkedList<>();
      for (NbGradleExtensionRef extensionRef : extensions) {
        String extensionName = extensionRef.getName();

        GradleModelDefQuery2 modelQuery = extensionRef.getModelNeeds().getQuery2();
        GradleModelDef modelDef = modelQuery.getModelDef(gradleTarget);

        models.addAll(modelDef.getToolingModels());
        addAllToMultiMap(extensionName, modelDef.getProjectInfoQueries(), projectInfoRequests);
        addAllToMultiMap(extensionName, modelDef.getToolingModels(), toolingModelNeeds);
      }

      modelFetcher = new GenericModelFetcher(buildInfoRequests, projectInfoRequests, models);
    }
    private NbGradleModel parseModel(
        FetchedProjectModels projectModels, Map<File, ProjectModelsOfExtensions> extensionModels) {
      Throwable issue = projectModels.getIssue();
      if (issue != null) {
        issues.add(ModelLoadIssues.projectModelLoadError(mainProject, projectModels, null, issue));
      }

      NbGradleMultiProjectDef projectDef =
          new NbGradleMultiProjectDef(projectModels.getProjectDef());
      NbGenericModelInfo genericInfo =
          new NbGenericModelInfo(projectDef, modelFetcher.getSettingsFile());
      NbGradleModel.Builder result = new NbGradleModel.Builder(genericInfo);

      File projectDir = genericInfo.getProjectDir();

      ProjectExtensionModelCache projectCache = cache.tryGetProjectCache(projectDir);

      for (NbGradleExtensionRef extension : extensions) {
        String extensionName = extension.getName();

        CachedModel cachedModel =
            projectCache != null ? projectCache.tryGetModel(extensionName) : null;

        Object extensionModel;
        if (cachedModel != null) {
          extensionModel = cachedModel.model;
        } else {
          ModelLoadResult modelLoadResult = modelLoadResultCache.get(extensionName);
          if (modelLoadResult == null) {
            modelLoadResult = getModelLoadResult(extension, projectDir, extensionModels);
            modelLoadResultCache.put(extensionName, modelLoadResult);
          } else {
            modelLoadResult = modelLoadResult.withMainProject(projectDir);
          }

          ParsedModel<?> parsedModels = extension.parseModel(modelLoadResult);
          extensionModel = parsedModels.getMainModel();

          for (Map.Entry<File, ?> entry : parsedModels.getOtherProjectsModel().entrySet()) {
            cache.getProjectCache(entry.getKey()).addModel(extensionName, entry.getValue());
          }
        }

        result.setModelForExtension(extension, extensionModel);
      }

      return result.create();
    }
    public List<Object> getToolingModelsForExtension(
        NbGradleExtensionRef extension, FetchedProjectModels projectModels) {

      List<Class<?>> needs = toolingModelNeeds.get(extension.getName());
      if (needs == null || needs.isEmpty()) {
        return Collections.emptyList();
      }

      Map<Class<?>, Object> allModels = projectModels.getToolingModels();
      List<Object> result = new ArrayList<>(needs.size());
      for (Class<?> need : needs) {
        Object model = allModels.get(need);
        if (model != null) {
          result.add(model);
        }
      }
      return result;
    }
    private ModelLoadResult getModelLoadResult(
        NbGradleExtensionRef extension,
        File defaultProjectDir,
        Map<File, ProjectModelsOfExtensions> extensionModels) {

      Map<File, Lookup> lookups = CollectionUtils.newHashMap(extensionModels.size());

      String extensionName = extension.getName();
      for (Map.Entry<File, ProjectModelsOfExtensions> entry : extensionModels.entrySet()) {
        Lookup lookup = entry.getValue().getExtensionLookups().get(extensionName);
        if (lookup == null) {
          lookup = Lookup.EMPTY;
        }
        lookups.put(entry.getKey(), lookup);
      }

      return new ModelLoadResult(defaultProjectDir, lookups);
    }
    private Map<String, Lookup> createLookups(FetchedProjectModels projectModels) {
      GenericProjectProperties genericProperties =
          projectModels.getProjectDef().getMainProject().getGenericProperties();

      Map<String, Lookup> result = CollectionUtils.newHashMap(extensions.size());
      for (NbGradleExtensionRef extension : extensions) {
        String extensionName = extension.getName();

        List<Object> models = new ArrayList<>();
        addProjectInfoResults(projectModels, extension, models);
        addAllNullSafe(models, modelFetcher.getToolingModelsForExtension(extension, projectModels));
        models.add(genericProperties);

        result.put(extensionName, Lookups.fixed(models.toArray()));
      }

      return result;
    }
    private void addProjectInfoResults(
        FetchedProjectModels projectModels, NbGradleExtensionRef extension, List<Object> results) {

      List<BuilderResult> builderResults =
          projectModels.getProjectInfoResults().get(extension.getName());
      if (builderResults == null) {
        return;
      }

      for (BuilderResult builderResult : builderResults) {
        BuilderIssue issue = builderResult.getIssue();
        if (issue != null) {
          issues.add(ModelLoadIssues.builderError(mainProject, projectModels, extension, issue));
        }

        Object resultObject = builderResult.getResultObject();
        if (resultObject != null) {
          results.add(resultObject);
        }
      }
    }