/*
* Copyright (c) 2010-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.repo.sql.query2.restriction;
import com.evolveum.midpoint.prism.query.NotFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.repo.sql.query.QueryException;
import com.evolveum.midpoint.repo.sql.query2.resolution.HqlEntityInstance;
import com.evolveum.midpoint.repo.sql.query2.InterpretationContext;
import com.evolveum.midpoint.repo.sql.query2.resolution.ItemPathResolver;
import com.evolveum.midpoint.repo.sql.query2.definition.JpaEntityDefinition;
import com.evolveum.midpoint.repo.sql.query2.hqm.condition.Condition;
import org.jetbrains.annotations.NotNull;
/**
* An image of an ObjectFilter, forming a restriction tree.
* Preserves some state related to the interpretation (translation).
* Provides functionality related to the translation.
*
* As for the state, we maintain (or, more precisely, we are able to determine) the following:
* - base HQL property path for the restriction
* - base EntityDefinition for the restriction
* - chain of translation states that led to the starting HQL property path (if applicable)
* This is stored in baseHqlEntity.
*
* Most restrictions do not change the above properties when propagating them to their children.
* However, Type and Exists restrictions do.
* The former changes EntityDefinition, the latter all three.
*
* Also, item-related restrictions may, at their own discretion, use an EntityDefinition that
* points to a subclass of the one provided by the parent restriction. They do that if the item
* referenced (e.g. location) is not available in the provided entity (e.g. RObject or RFocus or RAbstractRole),
* but has to be found deeper.
*
* There is one known problem in this respect, though: locality attribute. It is present in UserType as well as
* in OrgType. So, if having query like ObjectType: Equals(locality, 'abc') it might be narrowed
* as o.localityUser or o.locality. (Maybe there are other attributes like that, I don't know.)
*
* @author lazyman
* @author mederly
*/
public abstract class Restriction<T extends ObjectFilter> {
@NotNull final protected InterpretationContext context;
final protected Restriction parent;
@NotNull final protected T filter;
/**
* Content of ItemPathResolutionStartInformation:
*
* (1) Entity definition to be used as "root" by this restriction and its children.
*
* Looks a bit weird, but entity definition is provided to the restriction by the caller (query interpreter).
* Actually, the caller has to determine it, because it needs it to know what restriction to instantiate.
*
* (2) HQL property path of the object to which this restriction is to be applied.
*
* Usually, e.g. for simple cases like UserType: name, UserType: activation/administrativeStatus etc. the root
* is the query primary entity alias (e.g. u in "RUser u").
*
* For "Exists" filters children the base corresponds to the base item pointed to by the filter.
* E.g.
* - in "UserType: Exists (assignment)" it is "a" (provided that there is
* "RUser u left join u.assignments a with ..." already defined).
* - in "UserType: Exists (assignment/activation)" it is "a.activation"
* [although note that using single-valued properties as last path item
* in "Exists" filter is only a syntactic sugar]
*
* (3) List of translation steps that had led to the HQL property path. Useful for following ".."
* segments in item paths.
*
*/
private final HqlEntityInstance baseHqlEntity;
public Restriction(@NotNull InterpretationContext context, @NotNull T filter, @NotNull JpaEntityDefinition baseEntityDefinition, Restriction parent) {
this.context = context;
this.filter = filter;
this.parent = parent;
if (parent != null) {
baseHqlEntity = parent.getBaseHqlEntityForChildren().narrowFor(baseEntityDefinition);
} else {
baseHqlEntity = new HqlEntityInstance(context.getPrimaryEntityAlias(), baseEntityDefinition, null);
}
}
@NotNull
public T getFilter() {
return filter;
}
@NotNull
public InterpretationContext getContext() {
return context;
}
public Restriction getParent() {
return parent;
}
public HqlEntityInstance getBaseHqlEntity() {
return baseHqlEntity;
}
public abstract Condition interpret() throws QueryException;
protected boolean isNegated() {
return filter instanceof NotFilter || (parent != null && parent.isNegated());
}
protected String nameOf(Enum e) {
return e.getClass().getName() + "." + e.name();
}
public HqlEntityInstance getBaseHqlEntityForChildren() {
return getBaseHqlEntity();
}
protected ItemPathResolver getItemPathResolver() {
return getContext().getItemPathResolver();
}
}