use of com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition in project midpoint by Evolveum.
the class JpaAnyContainerDefinition method nextLinkDefinition.
@Override
public DataSearchResult nextLinkDefinition(ItemPath path, ItemDefinition itemDefinition, PrismContext prismContext) throws QueryException {
if (ItemPath.asSingleName(path) == null) {
throw new QueryException("Couldn't resolve paths other than those in the form of single name in extension/attributes container: " + path);
}
if (itemDefinition == null) {
throw new QueryException("Couldn't resolve dynamically defined item path '" + path + "' without proper definition");
}
CollectionSpecification collSpec = itemDefinition.isSingleValue() ? null : new CollectionSpecification();
// longs, strings, ...
String jpaName;
JpaDataNodeDefinition jpaNodeDefinition;
if (itemDefinition instanceof PrismPropertyDefinition) {
try {
jpaName = RAnyConverter.getAnySetType(itemDefinition, prismContext);
} catch (SchemaException e) {
throw new QueryException(e.getMessage(), e);
}
// TODO
jpaNodeDefinition = new JpaAnyPropertyDefinition(Object.class, null);
} else if (itemDefinition instanceof PrismReferenceDefinition) {
jpaName = "references";
jpaNodeDefinition = new JpaAnyReferenceDefinition(Object.class, RObject.class);
} else {
throw new QueryException("Unsupported 'any' item: " + itemDefinition);
}
JpaLinkDefinition<?> linkDefinition = new JpaAnyItemLinkDefinition(itemDefinition.getName(), jpaName, collSpec, getOwnerType(), jpaNodeDefinition);
return new DataSearchResult<>(linkDefinition, ItemPath.EMPTY_PATH);
}
use of com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition in project midpoint by Evolveum.
the class ItemPathResolutionState method nextState.
/**
* Executes transition to next state. Modifies query context by adding joins as necessary.
*
* Precondition: !isFinal()
* Precondition: adequate transition exists
*
* @param itemDefinition Target item definition (used/required only for "any" properties)
* @param singletonOnly Collections are forbidden
* @return destination state - always not null
*/
public ItemPathResolutionState nextState(ItemDefinition itemDefinition, boolean singletonOnly, PrismContext prismContext) throws QueryException {
// This is brutal hack, to be thought again.
if (remainingItemPath.startsWith(ParentPathSegment.class) && hqlDataInstance.getParentItem() != null) {
return new ItemPathResolutionState(remainingItemPath.tail(), hqlDataInstance.getParentItem(), itemPathResolver);
}
DataSearchResult<?> result = hqlDataInstance.getJpaDefinition().nextLinkDefinition(remainingItemPath, itemDefinition, prismContext);
LOGGER.trace("nextLinkDefinition on '{}' returned '{}'", remainingItemPath, result != null ? result.getLinkDefinition() : "(null)");
if (result == null) {
// sorry we failed (however, this should be caught before -> so IllegalStateException)
throw new IllegalStateException("Couldn't find '" + remainingItemPath + "' in " + hqlDataInstance.getJpaDefinition());
}
JpaLinkDefinition linkDefinition = result.getLinkDefinition();
String newHqlPath = hqlDataInstance.getHqlPath();
if (linkDefinition.hasJpaRepresentation()) {
if (singletonOnly && linkDefinition.isMultivalued()) {
// TODO better message + context
throw new QueryException("Collections are not allowable for right-side paths");
}
if (!linkDefinition.isEmbedded() || linkDefinition.isMultivalued()) {
LOGGER.trace("Adding join for '{}' to context", linkDefinition);
newHqlPath = itemPathResolver.addJoin(linkDefinition, hqlDataInstance.getHqlPath());
} else {
newHqlPath += "." + linkDefinition.getJpaName();
}
}
HqlDataInstance<?> parentDataInstance;
if (!remainingItemPath.startsWith(ParentPathSegment.class)) {
// TODO what about other special cases? (@, ...)
parentDataInstance = hqlDataInstance;
} else {
parentDataInstance = null;
}
return new ItemPathResolutionState(result.getRemainder(), new HqlDataInstance<>(newHqlPath, result.getTargetDefinition(), parentDataInstance), itemPathResolver);
}
use of com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition in project midpoint by Evolveum.
the class ItemPathResolver method addJoin.
String addJoin(JpaLinkDefinition joinedItemDefinition, String currentHqlPath) throws QueryException {
RootHibernateQuery hibernateQuery = context.getHibernateQuery();
String joinedItemJpaName = joinedItemDefinition.getJpaName();
String joinedItemFullPath = currentHqlPath + "." + joinedItemJpaName;
String joinedItemAlias;
if (!joinedItemDefinition.isMultivalued()) {
/*
* Let's check if we were already here i.e. if we had already created this join.
* This is to avoid useless creation of redundant joins for singleton items.
*
* But how can we be sure that item is singleton if we look only at the last segment (which is single-valued)?
* Imagine we are creating join for single-valued entity of u.abc.(...).xyz.ent where
* ent is single-valued and not embedded (so we are to create something like "left join u.abc.(...).xyz.ent e").
* Then "u" is certainly a single value: either the root object, or some value pointed to by Exists restriction.
* Also, abc, ..., xyz are surely single-valued: otherwise they would be connected by a join. So,
* u.abc.(...).xyz.ent is a singleton.
*
* Look at it in other way: if e.g. xyz was multivalued, then we would have something like:
* left join u.abc.(...).uvw.xyz x
* left join x.ent e
* And, therefore we would not be looking for u.abc.(...).xyz.ent.
*/
JoinSpecification existingJoin = hibernateQuery.getPrimaryEntity().findJoinFor(joinedItemFullPath);
if (existingJoin != null) {
// but let's check the condition as well
String existingAlias = existingJoin.getAlias();
// we have to create condition for existing alias, to be matched to existing condition
Condition conditionForExistingAlias = createJoinCondition(existingAlias, joinedItemDefinition, hibernateQuery);
if (ObjectUtils.equals(conditionForExistingAlias, existingJoin.getCondition())) {
LOGGER.trace("Reusing alias '{}' for joined path '{}'", existingAlias, joinedItemFullPath);
return existingAlias;
}
}
}
joinedItemAlias = hibernateQuery.createAlias(joinedItemDefinition);
Condition condition = createJoinCondition(joinedItemAlias, joinedItemDefinition, hibernateQuery);
hibernateQuery.getPrimaryEntity().addJoin(new JoinSpecification(joinedItemAlias, joinedItemFullPath, condition));
return joinedItemAlias;
}
use of com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition in project midpoint by Evolveum.
the class JpaEntityDefinition method nextLinkDefinition.
@Override
public DataSearchResult<?> nextLinkDefinition(ItemPath path, ItemDefinition<?> itemDefinition, PrismContext prismContext) throws QueryException {
if (ItemPath.isNullOrEmpty(path)) {
// doesn't fulfill precondition
return null;
}
ItemPathSegment first = path.first();
if (first instanceof IdItemPathSegment) {
throw new QueryException("ID item path segments are not allowed in query: " + path);
} else if (first instanceof ObjectReferencePathSegment) {
throw new QueryException("'@' path segment cannot be used in the context of an entity " + this);
}
JpaLinkDefinition<?> link = findRawLinkDefinition(path, JpaDataNodeDefinition.class, false);
if (link == null) {
return null;
} else {
link.resolveEntityPointer();
return new DataSearchResult<>(link, path.tail(link.getItemPath().size()));
}
}
use of com.evolveum.midpoint.repo.sql.query2.definition.JpaLinkDefinition in project midpoint by Evolveum.
the class ItemPathResolver method createJoinCondition.
private Condition createJoinCondition(String joinedItemAlias, JpaLinkDefinition joinedItemDefinition, RootHibernateQuery hibernateQuery) throws QueryException {
Condition condition = null;
if (joinedItemDefinition instanceof JpaAnyItemLinkDefinition) {
JpaAnyItemLinkDefinition anyLinkDef = (JpaAnyItemLinkDefinition) joinedItemDefinition;
AndCondition conjunction = hibernateQuery.createAnd();
if (anyLinkDef.getOwnerType() != null) {
// null for assignment extensions
conjunction.add(hibernateQuery.createEq(joinedItemAlias + ".ownerType", anyLinkDef.getOwnerType()));
}
conjunction.add(hibernateQuery.createEq(joinedItemAlias + "." + RAnyValue.F_NAME, RUtil.qnameToString(anyLinkDef.getItemName())));
condition = conjunction;
} else if (joinedItemDefinition.getCollectionSpecification() instanceof VirtualCollectionSpecification) {
VirtualCollectionSpecification vcd = (VirtualCollectionSpecification) joinedItemDefinition.getCollectionSpecification();
List<Condition> conditions = new ArrayList<>(vcd.getAdditionalParams().length);
for (VirtualQueryParam vqp : vcd.getAdditionalParams()) {
// e.g. name = "assignmentOwner", type = RAssignmentOwner.class, value = "ABSTRACT_ROLE"
Object value = createQueryParamValue(vqp);
Condition c = hibernateQuery.createEq(joinedItemAlias + "." + vqp.name(), value);
conditions.add(c);
}
if (conditions.size() > 1) {
condition = hibernateQuery.createAnd(conditions);
} else if (conditions.size() == 1) {
condition = conditions.iterator().next();
}
}
return condition;
}
Aggregations