@Override
  protected void align() throws Exception {
    super.align(); // do the schema matching part .. if any.

    if (alignInstances == true
        && (sourceOntology.getInstances() == null || targetOntology.getInstances() == null)) {
      // the source ontology or target ontology have no instances
      for (MatchingProgressListener mpd : progressDisplays) {
        mpd.appendToReport("Instances were NOT matched since they were not loaded properly.");
      }
    } else if (alignInstances && !this.isCancelled()) {
      sourceInstanceDataset = sourceOntology.getInstances();
      targetInstanceDataset = targetOntology.getInstances();

      // compile a list of source instances
      if (!sourceInstanceDataset.isIterable() && !targetInstanceDataset.isIterable()) {
        throw new AMException(
            "Neither the source or the target instance datasets are iterable.  We cannot instance match.");
      }

      if (!sourceInstanceDataset.isIterable()) {
        throw new AMException("The source MUST be an iterable instance dataset.");
      }

      Iterator<Instance> sourceInstances = sourceInstanceDataset.getInstances();

      // for every individual in the source list, look for candidate individuals in the target
      instanceAlignmentSet = alignInstances(sourceInstances);
    }
  }
  @Override
  protected void setupProgress() {
    super.setupProgress();

    if (alignInstances) {
      try {
        InstanceDataset instances = sourceOntology.getInstances();
        if (instances != null && instances.isIterable())
          stepsTotal += sourceOntology.getInstances().size();
      } catch (Exception e) {
        sLog.error("", e);
      }
    }
  }
  /**
   * @param sourceInstances
   * @return
   * @throws Exception
   */
  protected MatchingPairAlignment alignInstances(Iterator<Instance> sourceInstances)
      throws Exception {

    MatchingPairAlignment mappings = new MatchingPairAlignment();

    while (sourceInstances.hasNext()) {
      Instance currentInstance = sourceInstances.next();
      Set<String> labelList = currentInstance.getProperty(Instance.INST_LABEL);

      if (labelList == null) continue;

      // FIXME: Manage multiple labels.
      String label = labelList.iterator().next();

      label = processLabelBeforeCandidatesGeneration(label, currentInstance.getType());

      String sourceType = currentInstance.getTypeValue();
      List<MatchingPair> targetTypes = null;

      if (sourceType != null) {
        if (isUseInstanceSchemaMappings() && sourceOntology.getInstanceTypeMapping() != null) {
          HashMap<String, List<MatchingPair>> typeMapping = sourceOntology.getInstanceTypeMapping();
          if (typeMapping.containsKey(sourceType)) {
            targetTypes = typeMapping.get(sourceType);
          } else {
            targetTypes = null;
            // targetTypes = new ArrayList<MatchingPair>();
            // targetTypes.add( new MatchingPair(sourceType, sourceType)); // same type in the
            // target
          }
        }
      }

      // targetTypes = null;

      List<Instance> allCandidates = new ArrayList<Instance>();

      MatchingPair mapping = null;
      if (targetTypes != null) {
        for (MatchingPair mp : targetTypes) {
          Collection<Instance> targetCandidates =
              targetInstanceDataset.getCandidateInstances(label, mp.targetURI);
          allCandidates.addAll(targetCandidates);
        }
        mapping = alignInstanceCandidates(currentInstance, allCandidates);
      } else {
        Collection<Instance> targetCandidates =
            targetInstanceDataset.getCandidateInstances(label, null);
        allCandidates.addAll(targetCandidates);
        mapping = alignInstanceCandidates(currentInstance, allCandidates);
      }

      if (mapping != null) {
        System.out.println("Found mapping: " + mapping);
        mappings.add(mapping);
      }

      //			stepDone();
      //			updateProgress();
    }
    return mappings;
  }