gt:         if (referenceLibrarySuppliers.size() != pimSuppliers.size()) {
context: /*
   * This program and the accompanying materials are made available
   * under the terms of the Eclipse Public License v1.0 which
   * accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *   SEARCH Group, Incorporated - initial API and implementation
   *
   */
  package org.search.niem.uml.merge;
  
  import static org.apache.commons.lang.StringUtils.isBlank;
  import static org.eclipse.uml2.uml.util.UMLUtil.findNamedElements;
  import static org.eclipse.uml2.uml.util.UMLUtil.getBaseElement;
  import static org.search.niem.uml.util.CollectionExt.allAreNull;
  import static org.search.niem.uml.util.CollectionExt.anyIsNull;
  import static org.search.niem.uml.util.EcoreExt.get;
  import static org.search.niem.uml.util.EcoreExt.getEClass;
  import static org.search.niem.uml.util.EcoreExt.getNsURI;
  import static org.search.niem.uml.util.EcoreExt.getPackage;
  import static org.search.niem.uml.util.NIEMUmlExt.findNearestNiemNamespacePackage;
  import static org.search.niem.uml.util.NIEMUmlExt.getTargetNamespace;
  import static org.search.niem.uml.util.NIEMUmlExt.isNiemNamespace;
  import static org.search.niem.uml.util.NIEMUmlExt.isXmlPrimitiveType;
  import static org.search.niem.uml.util.NIEMUmlExt.namesMatch;
  import static org.search.niem.uml.util.UMLExt.getBody;
  import static org.search.niem.uml.util.UMLExt.getClients;
  import static org.search.niem.uml.util.UMLExt.getGeneral;
  import static org.search.niem.uml.util.UMLExt.getMemberEnds;
  import static org.search.niem.uml.util.UMLExt.getName;
  import static org.search.niem.uml.util.UMLExt.getOwner;
  import static org.search.niem.uml.util.UMLExt.getSuppliers;
  import static org.search.niem.uml.util.UMLExt.getType;
  import static org.search.niem.uml.util.UMLExt.isStereotypeApplication;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.LinkedList;
  import java.util.List;
  
  import org.apache.commons.lang.ObjectUtils;
  import org.eclipse.emf.ecore.EClass;
  import org.eclipse.emf.ecore.EObject;
  import org.eclipse.emf.ecore.EPackage;
  import org.eclipse.emf.ecore.EStructuralFeature;
  import org.eclipse.emf.ecore.util.EcoreUtil;
  import org.eclipse.uml2.uml.Classifier;
  import org.eclipse.uml2.uml.Element;
  import org.eclipse.uml2.uml.NamedElement;
  import org.eclipse.uml2.uml.Namespace;
  import org.eclipse.uml2.uml.Package;
  import org.eclipse.uml2.uml.Property;
  import org.eclipse.uml2.uml.Type;
  import org.search.niem.uml.util.EcoreExt;
  import org.search.niem.uml.util.UMLExt;
  
  public class NamespaceMergeUtil {
      public static Collection<Element> mapEquivalents(final Collection<EObject> referenceLibraryElements,
              final Package inThePIM) {
          final Collection<Element> pimEquivalents = new ArrayList<>();
  
          Namespace theCurrentOwner = null;
          Namespace theEquivalentOwnerInThePIM = null;
          for (final EObject visibleElement : referenceLibraryElements) {
              final Namespace theOwner = getOwner(visibleElement);
              if (theOwner != theCurrentOwner) {
                  theCurrentOwner = theOwner;
                  theEquivalentOwnerInThePIM = findEquivalent(theOwner, inThePIM);
              }
              if (theEquivalentOwnerInThePIM == null) {
                  continue;
              }
              final NamedElement theElement = theEquivalentOwnerInThePIM.getMember(getName(visibleElement), false,
                      getEClass(visibleElement));
              if (theElement != null) {
                  pimEquivalents.add(theElement);
              }
          }
  
          return pimEquivalents;
      }
  
      public static <T extends EObject> T findEquivalent(final T referenceLibraryElement, final Package inThePIM) {
          if (referenceLibraryElement == null) {
              return null;
          }
          if (isStereotypeApplication(referenceLibraryElement)) {
              @SuppressWarnings("unchecked")
              final T equivalentStereotypeApplication = (T) findEquivalentStereotypeApplication(referenceLibraryElement,
                      inThePIM);
              return equivalentStereotypeApplication;
          }
          if (!isBlank(UMLExt.getName(referenceLibraryElement))) {
              final NamedElement ne = (NamedElement) referenceLibraryElement;
              if (theNameIsUnique(ne)) {
                  return findEquivalentNamedElement(ne, inThePIM);
              }
          }
          final EObject inTheEquivalentParent = findEquivalent(getOwner(referenceLibraryElement), inThePIM);
          if (inTheEquivalentParent == null) {
              return null;
          }
          return findImmediatelyContainedEquivalent(referenceLibraryElement, inTheEquivalentParent, inThePIM);
      }
  
      private static <T extends EObject> T findEquivalentNamedElement(final NamedElement referenceLibraryElement,
              final Package inThePIM) {
          // first find the target namespace of the referenceLibraryElement
          final Package namespaceInTheReferenceLibrary = findNearestNiemNamespacePackage(referenceLibraryElement
                  .getNearestPackage());
          if (namespaceInTheReferenceLibrary == null) {
              return null;
          }
          // find the Package with the same targetNamespace in the PIM
          final Package namespaceInThePIM = findPackageWithTargetNamespace(inThePIM,
                  getTargetNamespace(namespaceInTheReferenceLibrary));
          if (namespaceInThePIM == null) {
              return null;
          }
          final LinkedList<Element> pathToReferenceLibraryElement = new LinkedList<>();
          NamedElement next = referenceLibraryElement;
          while (next != namespaceInTheReferenceLibrary) {
              pathToReferenceLibraryElement.addFirst(next);
              next = next.getNamespace();
          }
          return findNamedElement(namespaceInThePIM, pathToReferenceLibraryElement);
      }
  
      public static Element findMatching(final EObject referenceLibraryElement, final Element inTheNamespace) {
          for (final Element member : EcoreUtil.<Element> getObjectsByType(inTheNamespace.getOwnedElements(),
                  referenceLibraryElement.eClass())) {
              if (namesMatch(referenceLibraryElement, member)) {
                  return member;
              }
          }
          return null;
      }
  
      @SuppressWarnings("unchecked")
      private static <T extends EObject> T findNamedElement(final Package inTheNamespace, final Iterable<Element> withThePath) {
          // foreach path element, look for an element in the namespace with either a matching NIEMName, a matching name or, if
          // the path element ends with 'Type', the name without the 'Type' suffix
          Element nextNamespaceElement = inTheNamespace;
          for (final Element nextPathElement : withThePath) {
              final Element match = findMatching(nextPathElement, nextNamespaceElement);
              if (match == null) {
                  return null;
              }
              nextNamespaceElement = match;
          }
          return (T) nextNamespaceElement;
      }
  
      private static Package findPackageWithTargetNamespace(final Package inThePackage, final String targetNamespace) {
          if (isNiemNamespace(inThePackage) && areEqual(getTargetNamespace(inThePackage), targetNamespace)) {
              return inThePackage;
          }
          for (final Package p : inThePackage.getNestedPackages()) {
              final Package packageWithTargetNamespace = findPackageWithTargetNamespace(p, targetNamespace);
              if (packageWithTargetNamespace != null) {
                  return packageWithTargetNamespace;
              }
          }
          return null;
      }
  
      private static EObject findEquivalentStereotypeApplication(final EObject referenceLibraryElement, final Package inThePIM) {
          final Element pimEquivalentBaseElement = findEquivalent(getBaseElement(referenceLibraryElement), inThePIM);
          if (pimEquivalentBaseElement == null) {
              return null;
          }
          final Collection<EObject> equivalencies = new ArrayList<>();
          for (final EObject pimStereotypeApplication : pimEquivalentBaseElement.getStereotypeApplications()) {
              if (classesAreTheSame(referenceLibraryElement, pimStereotypeApplication)) {
                  equivalencies.add(pimStereotypeApplication);
              }
          }
          if (equivalencies.isEmpty()) {
              return null;
          }
          if (equivalencies.size() > 1) {
              Activator.INSTANCE.log("Ambiguous matches found for stereotype application " + referenceLibraryElement);
          }
          return equivalencies.iterator().next();
      }
  
      private static <T extends EObject> T findEquivalent(final T referenceLibraryElement,
              final Collection<T> inThePIMContents, final Package inThePIM) {
          final Collection<T> equivalencies = new ArrayList<>();
          for (final T aPIMElement : EcoreUtil.<T> getObjectsByType(inThePIMContents, referenceLibraryElement.eClass())) {
              if (areEquivalent(referenceLibraryElement, aPIMElement, inThePIM)) {
                  equivalencies.add(aPIMElement);
              }
          }
          if (equivalencies.isEmpty()) {
              return null;
          }
          if (equivalencies.size() > 1) {
              Activator.INSTANCE.log("Ambiguous matches found for element " + referenceLibraryElement);
          }
          return equivalencies.iterator().next();
      }
  
      private static <T extends EObject> T findImmediatelyContainedEquivalent(final T referenceLibraryElement,
              final EObject inThePIMElement, final Package inThePIM) {
          final EStructuralFeature feature = referenceLibraryElement.eContainingFeature();
          if (!inThePIMElement.eIsSet(feature)) {
              return null;
          }
          if (feature.isMany()) {
              return findEquivalent(referenceLibraryElement, EcoreExt.<T> getMany(feature, inThePIMElement), inThePIM);
          }
          final T child = get(feature, inThePIMElement);
          if (areEquivalent(referenceLibraryElement, child, inThePIM)) {
              return child;
          }
          return null;
      }
  
      private static boolean areEquivalent(final EObject aReferenceLibraryElement, final EObject aPIMElement,
              final Package inThePIM) {
          /* @formatter:off */
          return allAreNull(aReferenceLibraryElement, aPIMElement) ||
                  !anyIsNull(aReferenceLibraryElement, aPIMElement)
                  && classesAreTheSame(aReferenceLibraryElement, aPIMElement)
                  && namesAreTheSame(aReferenceLibraryElement, aPIMElement)
                  && bodiesAreTheSame(aReferenceLibraryElement, aPIMElement)
                  && typesAreEquivalent(aReferenceLibraryElement, aPIMElement, inThePIM)
                  && memberEndsAreEquivalent(aReferenceLibraryElement, aPIMElement, inThePIM)
                  && clientsAreEquivalent(aReferenceLibraryElement, aPIMElement, inThePIM)
                  && suppliersAreEquivalent(aReferenceLibraryElement, aPIMElement, inThePIM)
                  && generalsAreEquivalent(aReferenceLibraryElement, aPIMElement, inThePIM);
          /* @formatter:on */
      }
  
      private static boolean generalsAreEquivalent(final EObject aReferenceLibraryElement, final EObject aPIMElement,
              final Package inThePIM) {
          final Classifier referenceLibraryGeneral = getGeneral(aReferenceLibraryElement);
          final Classifier pimElementGeneral = getGeneral(aPIMElement);
          return isXmlPrimitiveType(referenceLibraryGeneral) ? areEqual(UMLExt.getName(referenceLibraryGeneral),
                  UMLExt.getName(pimElementGeneral)) : findEquivalent(referenceLibraryGeneral, inThePIM) == pimElementGeneral;
      }
  
      private static boolean clientsAreEquivalent(final EObject aReferenceLibraryElement, final EObject aPIMElement,
              final Package inThePIM) {
          final List<NamedElement> referenceLibraryClients = getClients(aReferenceLibraryElement);
          final List<NamedElement> pimClients = getClients(aPIMElement);
          if (referenceLibraryClients.size() != pimClients.size()) {
              return false;
          }
          for (int i = 0; i < referenceLibraryClients.size(); i++) {
              if (findEquivalent(referenceLibraryClients.get(i), inThePIM) != pimClients.get(i)) {
                  return false;
              }
          }
          return true;
      }
  
      private static boolean suppliersAreEquivalent(final EObject aReferenceLibraryElement, final EObject aPIMElement,
              final Package inThePIM) {
          final List<NamedElement> referenceLibrarySuppliers = getSuppliers(aReferenceLibraryElement);
          final List<NamedElement> pimSuppliers = getSuppliers(aPIMElement);
  