All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.lightblue.assoc.ResolvedFieldInfo Maven / Gradle / Ivy

There is a newer version: 2.18.0
Show newest version
/*
 Copyright 2013 Red Hat, Inc. and/or its affiliates.

 This file is part of lightblue.

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see .
 */
package com.redhat.lightblue.assoc;

import java.util.List;
import java.util.ArrayList;

import com.redhat.lightblue.query.FieldInfo;
import com.redhat.lightblue.query.QueryExpression;
import com.redhat.lightblue.query.GetQueryFields;

import com.redhat.lightblue.metadata.CompositeMetadata;
import com.redhat.lightblue.metadata.ResolvedReferenceField;
import com.redhat.lightblue.metadata.FieldTreeNode;
import com.redhat.lightblue.metadata.EntityMetadata;

import com.redhat.lightblue.util.Path;

public class ResolvedFieldInfo extends FieldInfo {

    /**
     * The field metadata
     */
    private final FieldTreeNode fieldNode;

    /**
     * The entity-relative field name
     */
    private final Path entityRelativeField;

    /**
     * The metadata of the entity containing the field
     */
    private final EntityMetadata fieldEntityMetadata;

    /**
     * The composite metadata of the entity containing the field
     */
    private final CompositeMetadata fieldCmd;

    /**
     * The query plan node associated with the field
     */
    private final QueryPlanNode qnode;

    public ResolvedFieldInfo(Path clauseFieldName,Path ctx,QueryExpression clause,
                             CompositeMetadata root,ResolvedReferenceField context,QueryPlan qplan) {
        super(clauseFieldName,ctx,clause);
        // Get the field node for the field, interpret field name with respect to context
        fieldNode=context==null?root.resolve(getFieldName()):context.getElement().resolve(getFieldName());
        ResolvedReferenceField rr=root.getResolvedReferenceOfField(fieldNode);
        if(rr==null)
            fieldEntityMetadata=fieldCmd=root;
        else {
            fieldEntityMetadata=rr.getOriginalMetadata();
            fieldCmd=rr.getReferencedMetadata();
        }
        entityRelativeField=getEntityRelativeFieldName(fieldNode.getFullPath(),getFieldName(),fieldCmd.getEntityPath());
        qnode=qplan.getNode(fieldCmd);
        if(qnode==null)
            throw new IllegalArgumentException("An entity referenced in a query is not in composite metadata."+
                                               " field:"+getFieldName()+" Composite metadata:"+fieldCmd);
    }

    /**
     * Returns the field metadata
     */
    public FieldTreeNode getFieldNode() {
        return fieldNode;
    }

    /**
     * Get the field name relative to the entity it is contained in
     */
    public Path getEntityRelativeFieldName() {
        return entityRelativeField;
    }

    /**
     * Returns the entity metadata for the entity containing this field.
     */
    public EntityMetadata getFieldEntityMetadata() {
        return fieldEntityMetadata;
    }

    /**
     * Returns the entity composite metatada
     */
    public CompositeMetadata getFieldEntityCompositeMetadata() {
        return fieldCmd;
    }

    public QueryPlanNode getFieldQueryPlanNode() {
        return qnode;
    }

    /**
     * Path is a normalized field name, like $parent.1.x.y. $parent can only appear at the beggining.
     * fullPath is the full name of the same field, something like a.b.*.x.y.
     * We calculate how many non-$parent segments path has, then we get that suffix of path,
     * remove that many elements from fullPath, and append to get a.b.1.x.y
     */
    private static Path removeParents(Path fullPath,Path path) {
        path=path.normalize();
        int pathN=path.numSegments();
        // We will go backwards until we see $parent or the beginning
        int nNonParent=0;
        for(int n=pathN-1;n>=0;n--) {
            if(path.head(n).equals(Path.PARENT))
                break;
            else
                nNonParent++;
        }
        return new Path(fullPath.prefix(-nNonParent),path.suffix(nNonParent));
    }

    /**
     * Rewrites a field name relative to its entity.
     *
     * @param fullPath the fullpath of the field name
     * @param path The field name as it appears in an expression. suffix of this should be the same as fullPath
     * @param cmdPrefix The metadata entity path for the composite metadata containing the field
     */
    public static Path getEntityRelativeFieldName(Path fullPath, Path path,Path cmdPrefix) {
        Path normalized=removeParents(fullPath,path);
        if(cmdPrefix.numSegments()>0)
            return normalized.suffix(-(cmdPrefix.numSegments()+1));
        else
            return normalized;
    }

    private static class GetFields extends GetQueryFields {
        private final CompositeMetadata root;
        private final ResolvedReferenceField context;
        private final QueryPlan qplan;
        
        public GetFields(List list,CompositeMetadata root,ResolvedReferenceField context,QueryPlan qplan) {
            super(list);
            this.root=root;
            this.context=context;
            this.qplan=qplan;
        }

        @Override
        protected ResolvedFieldInfo newFieldInfo(Path clauseField,Path ctx,QueryExpression clause) {
            return new ResolvedFieldInfo(clauseField,ctx,clause,root,context,qplan);
        }
    }

    public static List getQueryFields(QueryExpression q,
                                                         CompositeMetadata root,
                                                         ResolvedReferenceField context,
                                                         QueryPlan qplan) {
        List list=new ArrayList<>();
        new GetFields(list,root,context,qplan).iterate(q);
        return list;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy