private CriteriaInfoProvider getPathInfo(String path) {
    StringTokenizer tokens = new StringTokenizer(path, ".");
    String componentPath = "";

    // start with the 'rootProvider'
    CriteriaInfoProvider provider = nameCriteriaInfoMap.get(rootEntityName);

    while (tokens.hasMoreTokens()) {
      componentPath += tokens.nextToken();
      Type type = provider.getType(componentPath);
      if (type.isAssociationType()) {
        // CollectionTypes are always also AssociationTypes - but there's not always an associated
        // entity...
        AssociationType atype = (AssociationType) type;
        CollectionType ctype = type.isCollectionType() ? (CollectionType) type : null;
        Type elementType = (ctype != null) ? ctype.getElementType(sessionFactory) : null;
        // is the association a collection of components or value-types? (i.e a colloction of valued
        // types?)
        if (ctype != null && elementType.isComponentType()) {
          provider =
              new ComponentCollectionCriteriaInfoProvider(
                  helper.getCollectionPersister(ctype.getRole()));
        } else if (ctype != null && !elementType.isEntityType()) {
          provider = new ScalarCollectionCriteriaInfoProvider(helper, ctype.getRole());
        } else {
          provider =
              new EntityCriteriaInfoProvider(
                  (Queryable)
                      sessionFactory.getEntityPersister(
                          atype.getAssociatedEntityName(sessionFactory)));
        }

        componentPath = "";
      } else if (type.isComponentType()) {
        if (!tokens.hasMoreTokens()) {
          throw new QueryException(
              "Criteria objects cannot be created directly on components.  Create a criteria on owning entity and use a dotted property to access component property: "
                  + path);
        } else {
          componentPath += '.';
        }
      } else {
        throw new QueryException("not an association: " + componentPath);
      }
    }

    return provider;
  }
    /**
     * For each of the fields contained in this {@link Locks} object, parse out the type and the
     * field name and store those as the key and value in the "value" argument.
     */
    public void fillRelationships(SessionFactoryImplementor sfi, Map<String, Relationship> value) {

      final Type[] types = cm.getPropertyTypes();
      for (int t = 0; t < types.length; t++) {

        final Type type = types[t];
        final String name = type.getName();

        String to = null;
        Relationship field = null;
        if (type instanceof EntityType) {
          final EntityType entType = (EntityType) type;
          to = entType.getAssociatedEntityName();
          field = new Relationship(cm.getPropertyNames()[t], false);

        } else if (types[t] instanceof CollectionType) {
          final CollectionType colType = (CollectionType) types[t];
          final Type elemType = colType.getElementType(sfi);
          if (!elemType.isEntityType()) {
            continue; // The case for count maps and other primitives.
          }
          to = elemType.getName();

          int open = name.indexOf("(");
          int close = name.lastIndexOf(")");
          String role = name.substring(open + 1, close);
          int dot = role.lastIndexOf(".");
          field = new Relationship(role.substring(dot + 1), true);
        }

        if (to != null && field != null) {
          Map<String, ClassMetadata> m = sfi.getAllClassMetadata();
          for (Class<?> c : Impl.hierarchy(m, to)) {
            value.put(c.getName(), field);
          }
        }
      }
    }