docs: private TableAlias getTableAlias(String aPath, boolean useOuterJoins, UserAlias aUserAlias, String[] fieldRef, Map pathClasses)
  	{
          TableAlias curr, prev, indirect;
          String attr, attrPath = null;
          ObjectReferenceDescriptor ord;
          CollectionDescriptor cod;
          ClassDescriptor cld;
          Object[] prevKeys;
          Object[] keys;
          ArrayList descriptors;
          boolean outer = useOuterJoins;
          int pathLength;
          List hintClasses = null;       
          String pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(aPath);
          
          if (pathClasses != null)
          {
              hintClasses = (List) pathClasses.get(aPath);
          }    
          
          curr = getTableAliasForPath(aPath, pathAlias, hintClasses);
          if (curr != null)
          {
              return curr;
          }
  
  		descriptors = getRoot().cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  		prev = getRoot();
  
  		if (descriptors == null || descriptors.size() == 0)
  		{
  			if (prev.hasJoins())
  			{
  				for (Iterator itr = prev.iterateJoins(); itr.hasNext();)
  				{
  					prev = ((Join) itr.next()).left;
  					descriptors = prev.cld.getAttributeDescriptorsForPath(aPath, pathClasses);
  					if (descriptors.size() > 0)
  					{
  						break;
  					}
  				}
  			}
  		}
  
  		pathLength = descriptors.size();
  		for (int i = 0; i < pathLength; i++)
  		{
  			if (!(descriptors.get(i) instanceof ObjectReferenceDescriptor))
  			{
  				// only use Collection- and ObjectReferenceDescriptor
  				continue;
  			}
  
  			ord = (ObjectReferenceDescriptor) descriptors.get(i);
  			attr = ord.getAttributeName();
  			if (attrPath == null)
  			{
  				attrPath = attr;
  			}
  			else
  			{
  				attrPath = attrPath + "." + attr;
  			}
  
              // use clas hints for path
              if (pathClasses != null)
              {
                  hintClasses = (List) pathClasses.get(attrPath);     
              }    
  
  			// look for outer join hint
  			outer = outer || getQuery().isPathOuterJoin(attrPath);
  
  			// look for 1:n or m:n
  			if (ord instanceof CollectionDescriptor)
  			{
  				cod = (CollectionDescriptor) ord;
  				cld = getItemClassDescriptor(cod, hintClasses);
  
  				if (!cod.isMtoNRelation())
  				{
  					prevKeys = prev.cld.getPkFields();
  					keys = cod.getForeignKeyFieldDescriptors(cld);
  				}
  				else
  				{
  					String mnAttrPath = attrPath + "*";
  					String mnUserAlias = (aUserAlias == null ? null : aUserAlias + "*");
  					indirect = getTableAliasForPath(mnAttrPath, mnUserAlias, null);
  					if (indirect == null)
  					{
  						indirect = createTableAlias(cod.getIndirectionTable(), mnAttrPath, mnUserAlias);
  
  						// we need two Joins for m:n
  						// 1.) prev class to indirectionTable
  						prevKeys = prev.cld.getPkFields();
  						keys = cod.getFksToThisClass();
  						addJoin(prev, prevKeys, indirect, keys, outer, attr + "*");
  					}
  					// 2.) indirectionTable to the current Class
  					prev = indirect;
  					prevKeys = cod.getFksToItemClass();
  					keys = cld.getPkFields();
  				}
  			}
  			else
  			{
  				// must be n:1 or 1:1
  				cld = getItemClassDescriptor(ord, hintClasses);
  
  			    // BRJ : if ord is taken from 'super' we have to change prev accordingly
  				if (!prev.cld.equals(ord.getClassDescriptor()))
  				{
  					TableAlias ordAlias = getTableAliasForClassDescriptor(ord.getClassDescriptor());
  					Join join = prev.getJoin(ordAlias);
                      if (join != null)
                      {
                          join.isOuter = join.isOuter || outer;
                      }    
  				    prev = ordAlias;
  				}	
  
  				prevKeys = ord.getForeignKeyFieldDescriptors(prev.cld);
  				keys = cld.getPkFields();
  
  				// [olegnitz]
  				// a special case: the last element of the path is
  				// reference and the field is one of PK fields =>
  				// use the correspondent foreign key field, don't add the join
  				if ((fieldRef != null) && (i == (pathLength - 1)))
  				{
  					FieldDescriptor[] pk = cld.getPkFields();
  
  					for (int j = 0; j < pk.length; j++)
  					{
  						if (pk[j].getAttributeName().equals(fieldRef[0]))
  						{
  							fieldRef[0] = ((FieldDescriptor) prevKeys[j]).getAttributeName();
  							return prev;
  						}
  					}
  				}
  			}
  
  			pathAlias = aUserAlias == null ? null : aUserAlias.getAlias(attrPath);
  			curr = getTableAliasForPath(attrPath, pathAlias, hintClasses);
  
  			if (curr == null)
  			{
  				curr = createTableAlias(cld, attrPath, pathAlias, hintClasses);
  
  				outer = outer || (curr.cld == prev.cld) || curr.hasExtents() || useOuterJoins;
  				addJoin(prev, prevKeys, curr, keys, outer, attr);
  
  				buildSuperJoinTree(curr, cld, aPath, outer);
  			}
  
  			prev = curr;
  		}
  
  		m_logger.debug("Result of getTableAlias(): " + curr);
  		return curr;
  	}