com.evolveum.midpoint.repo.sql.query.restriction.ReferenceRestriction.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.repo.sql.query.restriction.ReferenceRestriction.java

Source

/*
 * 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.query.restriction;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.repo.sql.data.common.ObjectReference;
import com.evolveum.midpoint.repo.sql.query.QueryException;
import com.evolveum.midpoint.repo.sql.query.QueryContext;
import com.evolveum.midpoint.repo.sql.query.definition.CollectionDefinition;
import com.evolveum.midpoint.repo.sql.query.definition.Definition;
import com.evolveum.midpoint.repo.sql.query.definition.EntityDefinition;
import com.evolveum.midpoint.repo.sql.query.definition.PropertyDefinition;
import com.evolveum.midpoint.repo.sql.query.definition.ReferenceDefinition;
import com.evolveum.midpoint.repo.sql.util.ClassMapper;
import com.evolveum.midpoint.repo.sql.util.RUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;

import javax.xml.namespace.QName;

import java.util.List;

/**
 * @author lazyman
 */
public class ReferenceRestriction extends ItemRestriction<RefFilter> {

    @Override
    public boolean canHandle(ObjectFilter filter) {
        if (filter instanceof RefFilter) {
            return true;
        }
        return false;
    }

    // modelled after PropertyRestriction.interpretInternal, with some differences
    @Override
    public Criterion interpretInternal(RefFilter filter) throws QueryException {

        // let's check the value (null is not supported yet)
        List<? extends PrismValue> values = filter.getValues();
        if (values != null && values.size() > 1) {
            throw new QueryException("Ref filter '" + filter
                    + "' contain more than one reference value (which is not supported for now).");
        }
        PrismReferenceValue refValue = null;
        if (values != null && !values.isEmpty()) {
            refValue = (PrismReferenceValue) values.get(0);
        }

        QueryContext context = getContext();

        ItemPath fullPath = filter.getFullPath();
        // actually, we cannot look for ReferenceDefinition here, because e.g. linkRef has a CollectionDefinition
        Definition def = findProperDefinition(fullPath, Definition.class);
        if (def == null) {
            throw new QueryException("Definition for " + fullPath + " couldn't be found.");
        }

        // ugly hacking, todo refactor!
        StringBuilder sb = new StringBuilder();
        if (def instanceof ReferenceDefinition) {
            ItemPath parentPath = filter.getParentPath();
            // hack: construction/resourceRef->resourceRef
            if (QNameUtil.match(ConstructionType.F_RESOURCE_REF, filter.getElementName()) && parentPath != null
                    && parentPath.last() instanceof NameItemPathSegment && QNameUtil.match(
                            AssignmentType.F_CONSTRUCTION, ((NameItemPathSegment) parentPath.last()).getName())) {
                parentPath = parentPath.allExceptLast();
            }
            String alias = context.getAlias(parentPath);
            if (StringUtils.isNotEmpty(alias)) {
                sb.append(alias);
                sb.append('.');
            }
            sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly]
            String referenceName = def.getJpaName();
            sb.append(referenceName);
            sb.append(".");
        } else {
            String alias = context.getAlias(filter.getPath());
            if (StringUtils.isNotEmpty(alias)) {
                sb.append(alias);
                sb.append('.');
            }
            sb.append(createPropertyOrReferenceNamePrefix(filter.getPath())); // i'm not sure about this [mederly]
        }
        String prefix = sb.toString();

        String refValueOid = null;
        QName refValueRelation = null;
        QName refValueTargetType = null;
        if (refValue != null) {
            refValueOid = refValue.getOid();
            refValueRelation = refValue.getRelation();
            refValueTargetType = refValue.getTargetType();
        }
        Conjunction conjunction = Restrictions.conjunction();
        conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TARGET_OID, refValueOid));

        if (refValueOid != null) {
            if (refValueRelation == null) {
                // Return only references without relation
                conjunction.add(Restrictions.eq(prefix + ObjectReference.F_RELATION, RUtil.QNAME_DELIMITER));
            } else if (refValueRelation.equals(PrismConstants.Q_ANY)) {
                // Return all relations => no restriction
            } else {
                // return references with specific relation
                conjunction.add(
                        handleEqOrNull(prefix + ObjectReference.F_RELATION, RUtil.qnameToString(refValueRelation)));
            }

            if (refValueTargetType != null) {
                conjunction.add(handleEqOrNull(prefix + ObjectReference.F_TYPE,
                        ClassMapper.getHQLTypeForQName(refValueTargetType)));
            }
        }

        // TODO what about isNotNull if necessary ?

        return conjunction;
    }

    @Override
    public ReferenceRestriction newInstance() {
        return new ReferenceRestriction();
    }

    private Criterion handleEqOrNull(String propertyName, Object value) {
        if (value == null) {
            return Restrictions.isNull(propertyName);
        }

        return Restrictions.eq(propertyName, value);
    }
}