/* * 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.definition; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.Visitable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.repo.sql.query.QueryException; import com.evolveum.midpoint.repo.sql.query2.resolution.DataSearchResult; import com.evolveum.midpoint.util.DebugDumpable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Defines piece of JPA data - entity, property, reference, or "any" container. Used to convert ItemPath to HQL query, * or, specifically, to a property path with left outer joins where appropriate. * * The conversion works like running state machine where data definitions are states, and transitions are labeled * with non-empty ItemPaths. Input paths are used to navigate through states until all of input path is consumed. * * In addition to recognize input paths, this automaton produces HQL path and property joins. That's why * each possible transition is labeled with (ItemPath prefix, JPA name, other transition data) tuple. * ItemPath prefix is used to match the input path, while JPA name + other transition data, along * with target state information (potentially) are used to generate HQL property path with appropriate join, * if necessary. * * Note that some transitions may have empty JPA name - when the data is contained directly in owner entity * (e.g. object extension, shadow attributes). Most transitions have single item paths. However, some have two, * e.g. construction/resourceRef, owner/id, metadata/*. * * By other transition data we currently mean: collection specification, or "embedded" flag. * * Terminology: * - state ~ data node (JpaDataNodeDefinition -> JpaEntityDefinition, JpaPropertyDefinition, ...) * - transition ~ link node (JpaLinkDefinition) * * @author mederly */ public abstract class JpaDataNodeDefinition implements DebugDumpable, Visitable { /** * JPA class - either "composite" (RObject, RUser, RAssignment, ...) or "primitive" (String, Integer, int, ...) */ @NotNull private final Class jpaClass; /** * JAXB class - either "composite" (ObjectType, UserType, AssignmentType, ...) or "primitive" (String, Integer, int, ...) * Null if not known. */ @Nullable private final Class jaxbClass; public JpaDataNodeDefinition(@NotNull Class jpaClass, @Nullable Class jaxbClass) { this.jpaClass = jpaClass; this.jaxbClass = jaxbClass; } @NotNull public Class getJpaClass() { return jpaClass; } public String getJpaClassName() { return jpaClass.getSimpleName(); } @Nullable public Class getJaxbClass() { return jaxbClass; } /** * Tries to find "next step" in the translation process for a given ItemPath. * * @param path A path to be resolved. Always non-null and non-empty. Should produce at least one transition. * @param itemDefinition Item definition for the item being sought. Needed only for "any" items. * @return * - Normally it returns the search result containing next item definition (entity, collection, ...) in the chain * and the unresolved remainder of the path. The transition may be empty ("self") e.g. for metadata or construction. * - If the search was not successful, returns null. * */ public abstract DataSearchResult<?> nextLinkDefinition(ItemPath path, ItemDefinition<?> itemDefinition, PrismContext prismContext) throws QueryException; public String toString() { return getShortInfo(); } protected abstract String getDebugDumpClassName(); @Override public String debugDump() { return debugDump(0); } public String getShortInfo() { StringBuilder sb = new StringBuilder(); sb.append(getDebugDumpClassName()).append(':').append(getJpaClassName()); if (jaxbClass != null) { sb.append(" (jaxb=").append(jaxbClass.getSimpleName()).append(")"); } return sb.toString(); } }