// TODO we could cache such knowledge in a service if that turns out to be costly private String buildCollectionRole(OgmCollectionPersister collectionPersister) { String otherSidePropertyName = null; Loadable elementPersister = (Loadable) collectionPersister.getElementPersister(); Type[] propertyTypes = elementPersister.getPropertyTypes(); for (int index = 0; index < propertyTypes.length; index++) { Type type = propertyTypes[index]; // we try and restrict type search as much as possible if (type.isAssociationType()) { boolean matching = false; // if the main side collection is a one-to-many, the reverse side should be a to-one is not // a collection if (collectionPersister.isOneToMany() && !type.isCollectionType()) { matching = isToOneMatching(elementPersister, index, type); } // if the main side collection is not a one-to-many, the reverse side should be a collection else if (!collectionPersister.isOneToMany() && type.isCollectionType()) { matching = isCollectionMatching((CollectionType) type, collectionPersister.getTableName()); } if (matching) { otherSidePropertyName = elementPersister.getPropertyNames()[index]; break; } } } return processOtherSidePropertyName(otherSidePropertyName); }
private Queryable determineAppropriateOwnerPersister(NonScalarReturn ownerDescriptor) { String entityName = null; if (ownerDescriptor instanceof RootReturn) { entityName = ((RootReturn) ownerDescriptor).getEntityName(); } else if (ownerDescriptor instanceof CollectionReturn) { CollectionReturn collRtn = (CollectionReturn) ownerDescriptor; String role = collRtn.getOwnerEntityName() + "." + collRtn.getOwnerProperty(); CollectionPersister persister = getFactory().getCollectionPersister(role); EntityType ownerType = (EntityType) persister.getElementType(); entityName = ownerType.getAssociatedEntityName(getFactory()); } else if (ownerDescriptor instanceof FetchReturn) { FetchReturn fetchRtn = (FetchReturn) ownerDescriptor; Queryable persister = determineAppropriateOwnerPersister(fetchRtn.getOwner()); Type ownerType = persister.getPropertyType(fetchRtn.getOwnerProperty()); if (ownerType.isEntityType()) { entityName = ((EntityType) ownerType).getAssociatedEntityName(getFactory()); } else if (ownerType.isCollectionType()) { Type ownerCollectionElementType = ((CollectionType) ownerType).getElementType(getFactory()); if (ownerCollectionElementType.isEntityType()) { entityName = ((EntityType) ownerCollectionElementType).getAssociatedEntityName(getFactory()); } } } if (entityName == null) { throw new HibernateException("Could not determine fetch owner : " + ownerDescriptor); } return (Queryable) getFactory().getEntityPersister(entityName); }
private FromElement createCollectionJoin(JoinSequence collectionJoinSequence, String tableAlias) throws SemanticException { String text = queryableCollection.getTableName(); AST ast = createFromElement(text); FromElement destination = (FromElement) ast; Type elementType = queryableCollection.getElementType(); if (elementType.isCollectionType()) { throw new SemanticException("Collections of collections are not supported!"); } destination.initializeCollection(fromClause, classAlias, tableAlias); destination.setType(JOIN_FRAGMENT); // Tag this node as a JOIN. destination.setIncludeSubclasses(false); // Don't include subclasses in the join. destination.setCollectionJoin(true); // This is a clollection join. destination.setJoinSequence(collectionJoinSequence); destination.setOrigin(origin, false); destination.setCollectionTableAlias(tableAlias); // origin.addDestination( destination ); // This was the cause of HHH-242 // origin.setType( FROM_FRAGMENT ); // Set the parent node type so that the AST is properly // formed. origin.setText(""); // The destination node will have all the FROM text. origin.setCollectionJoin( true); // The parent node is a collection join too (voodoo - see JoinProcessor) fromClause.addCollectionJoinFromElementByPath(path, destination); fromClause.getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces()); return destination; }
private boolean indicatesCollection(Type type) { if (type.isCollectionType()) { return true; } else if (type.isComponentType()) { Type[] subtypes = ((CompositeType) type).getSubtypes(); for (int i = 0; i < subtypes.length; i++) { if (indicatesCollection(subtypes[i])) { return true; } } } return false; }
protected void setRelatedClassType( GrailsHibernateDomainClassProperty prop, AssociationType assType, Type hibernateType) { try { String associatedEntity = assType.getAssociatedEntityName((SessionFactoryImplementor) getSessionFactory()); ClassMetadata associatedMetaData = getSessionFactory().getClassMetadata(associatedEntity); prop.setRelatedClassType(associatedMetaData.getMappedClass(EntityMode.POJO)); } catch (MappingException me) { // other side must be a value object if (hibernateType.isCollectionType()) { prop.setRelatedClassType(Collection.class); } } }
// TODO we could cache such knowledge in a service if that turns out to be costly private String getCollectionRoleFromToOne(OgmEntityPersister associatedPersister) { // code logic is slightly duplicated but the input and context is different, hence this choice Type[] propertyTypes = associatedPersister.getPropertyTypes(); String otherSidePropertyName = null; for (int index = 0; index < propertyTypes.length; index++) { Type type = propertyTypes[index]; boolean matching = false; // we try and restrict type search as much as possible // we look for associations that also are collections if (type.isAssociationType() && type.isCollectionType()) { matching = isCollectionMatching((CollectionType) type, tableName); } // we look for associations that are to-one else if (type.isAssociationType() && !type.isCollectionType()) { // isCollectionType redundant but kept for readability matching = isToOneMatching(associatedPersister, index, type); } if (matching) { otherSidePropertyName = associatedPersister.getPropertyNames()[index]; break; } } return processOtherSidePropertyName(otherSidePropertyName); }
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; }
public void end(QueryTranslatorImpl q) throws QueryException { ignoreInitialJoin = false; Type propertyType = getPropertyType(); if (propertyType != null && propertyType.isCollectionType()) { collectionRole = ((CollectionType) propertyType).getRole(); collectionName = q.createNameForCollection(collectionRole); prepareForIndex(q); } else { columns = currentColumns(); setType(); } // important!! continuation = false; }
private static NonIdentifierAttributeNature decode(Type type) { if (type.isAssociationType()) { AssociationType associationType = (AssociationType) type; if (type.isComponentType()) { // an any type is both an association and a composite... return NonIdentifierAttributeNature.ANY; } return type.isCollectionType() ? NonIdentifierAttributeNature.COLLECTION : NonIdentifierAttributeNature.ENTITY; } else { if (type.isComponentType()) { return NonIdentifierAttributeNature.COMPOSITE; } return NonIdentifierAttributeNature.BASIC; } }
private List<String> getCollectionRoles( final SessionFactory sessionFactory, final Class<?> entityClass) { List<String> collectionRoles = entityCollectionRoles.get(entityClass); if (collectionRoles != null) { return collectionRoles; } final com.google.common.collect.ImmutableList.Builder<String> collectionRolesBuilder = ImmutableList.builder(); final ClassMetadata classMetadata = sessionFactory.getClassMetadata(entityClass); for (final Type type : classMetadata.getPropertyTypes()) { if (type.isCollectionType()) { collectionRolesBuilder.add(((CollectionType) type).getRole()); } } collectionRoles = collectionRolesBuilder.build(); entityCollectionRoles.put(entityClass, collectionRoles); return collectionRoles; }
protected QueryableCollection getQueryableCollection( String entityName, String propertyName, SessionFactoryImplementor factory) throws HibernateException { PropertyMapping ownerMapping = (PropertyMapping) factory.getEntityPersister(entityName); Type type = ownerMapping.toType(propertyName); if (!type.isCollectionType()) { throw new MappingException( "Property path [" + entityName + "." + propertyName + "] does not reference a collection"); } String role = ((CollectionType) type).getRole(); try { return (QueryableCollection) factory.getCollectionPersister(role); } catch (ClassCastException cce) { throw new QueryException("collection role is not queryable: " + role); } catch (Exception e) { throw new QueryException("collection role not found: " + role); } }
public void token(String token, QueryTranslatorImpl q) throws QueryException { if (token != null) path.append(token); String alias = q.getPathAlias(path.toString()); if (alias != null) { reset(q); // reset the dotcount (but not the path) currentName = alias; // after reset! currentPropertyMapping = q.getPropertyMapping(currentName); if (!ignoreInitialJoin) { JoinSequence ojf = q.getPathJoin(path.toString()); try { joinSequence.addCondition( ojf.toJoinFragment(q.getEnabledFilters(), true) .toWhereFragmentString()); // after reset! } catch (MappingException me) { throw new QueryException(me); } // we don't need to worry about any condition in the ON clause // here (toFromFragmentString), since anything in the ON condition // is already applied to the whole query } } else if (".".equals(token)) { dotcount++; } else { if (dotcount == 0) { if (!continuation) { if (!q.isName(token)) throw new QueryException("undefined alias: " + token); currentName = token; currentPropertyMapping = q.getPropertyMapping(currentName); } } else if (dotcount == 1) { if (currentName != null) { currentProperty = token; } else if (collectionName != null) { // processCollectionProperty(token, q.getCollectionPersister(collectionRole), // collectionName); continuation = false; } else { throw new QueryException("unexpected"); } } else { // dotcount>=2 // Do the corresponding RHS Type propertyType = getPropertyType(); if (propertyType == null) { throw new QueryException("unresolved property: " + path); } if (propertyType.isComponentType()) { dereferenceComponent(token); } else if (propertyType.isEntityType()) { if (!isCollectionValued()) dereferenceEntity(token, (EntityType) propertyType, q); } else if (propertyType.isCollectionType()) { dereferenceCollection(token, ((CollectionType) propertyType).getRole(), q); } else { if (token != null) throw new QueryException("dereferenced: " + path); } } } }