public String addFromCollection(QueryTranslatorImpl q) throws QueryException {
    Type collectionElementType = getPropertyType();

    if (collectionElementType == null) {
      throw new QueryException(
          "must specify 'elements' for collection valued property in from clause: " + path);
    }

    if (collectionElementType.isEntityType()) {
      // an association
      QueryableCollection collectionPersister = q.getCollectionPersister(collectionRole);
      Queryable entityPersister = (Queryable) collectionPersister.getElementPersister();
      String clazz = entityPersister.getEntityName();

      final String elementName;
      if (collectionPersister.isOneToMany()) {
        elementName = collectionName;
        // allow index() function:
        q.decoratePropertyMapping(elementName, collectionPersister);
      } else { // many-to-many
        q.addCollection(collectionName, collectionRole);
        elementName = q.createNameFor(clazz);
        addJoin(elementName, (AssociationType) collectionElementType);
      }
      q.addFrom(elementName, clazz, joinSequence);
      currentPropertyMapping = new CollectionPropertyMapping(collectionPersister);
      return elementName;
    } else {
      // collections of values
      q.addFromCollection(collectionName, collectionRole, joinSequence);
      return collectionName;
    }
  }
 String continueFromManyToMany(String entityName, String[] joinColumns, QueryTranslatorImpl q)
     throws QueryException {
   start(q);
   continuation = true;
   currentName = q.createNameFor(entityName);
   q.addType(currentName, entityName);
   Queryable classPersister = q.getEntityPersister(entityName);
   // QueryJoinFragment join = q.createJoinFragment(useThetaStyleJoin);
   addJoin(
       currentName,
       q.getFactory().getTypeResolver().getTypeFactory().manyToOne(entityName),
       joinColumns);
   currentPropertyMapping = classPersister;
   return currentName;
 }
  private void dereferenceEntity(
      String propertyName, EntityType propertyType, QueryTranslatorImpl q) throws QueryException {
    // NOTE: we avoid joining to the next table if the named property is just the foreign key value

    // if its "id"
    boolean isIdShortcut =
        EntityPersister.ENTITY_ID.equals(propertyName) && propertyType.isReferenceToPrimaryKey();

    // or its the id property name
    final String idPropertyName;
    try {
      idPropertyName = propertyType.getIdentifierOrUniqueKeyPropertyName(q.getFactory());
    } catch (MappingException me) {
      throw new QueryException(me);
    }
    boolean isNamedIdPropertyShortcut =
        idPropertyName != null
            && idPropertyName.equals(propertyName)
            && propertyType.isReferenceToPrimaryKey();

    if (isIdShortcut || isNamedIdPropertyShortcut) {
      // special shortcut for id properties, skip the join!
      // this must only occur at the _end_ of a path expression
      if (componentPath.length() > 0) componentPath.append('.');
      componentPath.append(propertyName);
    } else {
      String entityClass = propertyType.getAssociatedEntityName();
      String name = q.createNameFor(entityClass);
      q.addType(name, entityClass);
      addJoin(name, propertyType);
      if (propertyType.isOneToOne()) oneToOneOwnerName = currentName;
      ownerAssociationType = propertyType;
      currentName = name;
      currentProperty = propertyName;
      q.addPathAliasAndJoin(
          path.substring(0, path.toString().lastIndexOf('.')), name, joinSequence.copy());
      componentPath.setLength(0);
      currentPropertyMapping = q.getEntityPersister(entityClass);
    }
  }