Package org.jpox.store.mapped.expression

Source Code of org.jpox.store.mapped.expression.LogicSetExpression

/**********************************************************************
Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
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.

Contributors:
2003 Erik Bengtson - fixed bug [833915] QueryResult passed as parameter
            for another Query
2003 Andy Jefferson - coding standards
2005 Andy Jefferson - added embedded PC handling, and checks for non-existent fields
2005 Andy Jefferson - added nested embedded field capability
    ...
**********************************************************************/
package org.jpox.store.mapped.expression;

import java.util.HashMap;
import java.util.Map;

import org.jpox.ObjectManagerFactoryImpl;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.store.exceptions.NoSuchPersistentFieldException;
import org.jpox.store.mapped.DatastoreClass;
import org.jpox.store.mapped.DatastoreCollection;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.DatastoreElementContainer;
import org.jpox.store.mapped.DatastoreField;
import org.jpox.store.mapped.DatastoreIdentifier;
import org.jpox.store.mapped.DatastoreMap;
import org.jpox.store.mapped.DatastoreObject;
import org.jpox.store.mapped.mapping.EmbeddedElementPCMapping;
import org.jpox.store.mapped.mapping.EmbeddedKeyPCMapping;
import org.jpox.store.mapped.mapping.EmbeddedMapping;
import org.jpox.store.mapped.mapping.EmbeddedPCMapping;
import org.jpox.store.mapped.mapping.EmbeddedValuePCMapping;
import org.jpox.store.mapped.mapping.JavaTypeMapping;
import org.jpox.util.Localiser;

/**
* Represents a Set. A collection of objects. For in-depth details read about the mathematical "set" theory.
*
* Pragmatically, it represents a SQL table expression as might be listed
* in the FROM clause of a SELECT statement.
* A table expression is a fragment of a larger containing QueryStatement.
* <p>
* A table expression has a base "main" table.
* If that table serves as backing for a Java class, and that class has persistence-capable superclasses,
* then the table expression may include joins to superclass tables, or may cause such joins to occur in its
* surrounding QueryStatement.
*
* @see QueryExpression
*/
public abstract class LogicSetExpression
{
    /** Localiser for messages */
    protected static final Localiser LOCALISER = Localiser.getInstance("org.jpox.store.Localisation",
        ObjectManagerFactoryImpl.class.getClassLoader());

    /** Query Expression that this is part of. */
    protected final QueryExpression qs;

    /** The datastore table underlying this expression. */
    protected final DatastoreContainerObject mainTable;

    /** Alias for this table. */
    protected final DatastoreIdentifier mainAlias;

    /** The SQL text. */
    protected String sqlText = null;

    /** Collection of field expressions already created for this table expression. Used by nested embedded queries. */
    protected Map embeddedFieldMappings = null;

    /**
     * Constructor.
     * @param qs Query Expression
     * @param mainTable The main table for this query
     * @param alias Table alias
     */
    protected LogicSetExpression(QueryExpression qs, DatastoreContainerObject mainTable, DatastoreIdentifier alias)
    {
        this.qs = qs;
        this.mainTable = mainTable;
        this.mainAlias = alias;
    }

    protected void assertNotFrozen()
    {
        if (sqlText != null)
        {
         //   throw new JPOXUserException("A table expression cannot be modified after being output");
        }
    }

    /**
     * Accessor for the main table for this expression.
     * @return The main table
     */
    public final DatastoreObject getMainTable()
    {
        return mainTable;
    }

    /**
     * Accessor for the alias for this table expression.
     * @return The alias
     */
    public final DatastoreIdentifier getAlias()
    {
        return mainAlias;
    }

    /**
     * Accessor for a field expression on this table where the field is actually present in this table.
     * @param fieldName Name of the field
     * @return The field expression
     */
    public ScalarExpression newFieldExpression(String fieldName)
    {
        if (mainTable instanceof DatastoreClass)
        {
            // Field of class in its primary/secondary table
            DatastoreClass ct = (DatastoreClass) mainTable;
            JavaTypeMapping m = null;
            if (fieldName.equals(qs.getCandidateAlias()))
            {
                // Candidate table so return id mapping
                m = ct.getIDMapping();
                return m.newScalarExpression(qs, this);
            }
            else
            {
                if (fieldName.indexOf(".") > 0)
                {
                    String baseField = fieldName.substring(0, fieldName.indexOf("."));
                    try
                    {
                        m = ct.getFieldMapping(baseField);
                    }
                    catch (NoSuchPersistentFieldException npfe)
                    {
                        // Check if this field is a previously utilised embedded field
                        if (embeddedFieldMappings != null)
                        {
                            m = (JavaTypeMapping)embeddedFieldMappings.get(baseField);
                        }
                        if (m == null)
                        {
                            // Field is not valid for this class, and we have no known embedded mapping for it so its a user error
                            throw npfe;
                        }
                    }
                    if (m == null)
                    {
                        throw new JPOXUserException(LOCALISER.msg("037001", fieldName, ct.toString()));
                    }
                   
                    if (m instanceof EmbeddedPCMapping)
                    {
                        // Embedded PC field
                        String subField = fieldName.substring(fieldName.indexOf(".") + 1);
                        m = getMappingForEmbeddedField((EmbeddedPCMapping)m, subField);
                        if (m == null)
                        {
                            throw new JPOXUserException(LOCALISER.msg("037002", fieldName, subField, baseField));
                        }
                        // Save this embedded mapping in case the user has nested subobjects within it
                        // TODO This doesnt allow for embedded "subfields" having the same name as other embedded subfields
                        // Currently we just keep on saving these against the subfield name, but maybe we only to keep the
                        // most recent since the field will be processed straight away if it's part of a JDOQL query
                        if (embeddedFieldMappings == null)
                        {
                            embeddedFieldMappings = new HashMap();
                        }
                        embeddedFieldMappings.put(subField, m);
                    }
                   
                    ScalarExpression expr = m.newScalarExpression(qs, this);
                    if (expr instanceof ObjectExpression)
                    {
                        ((ObjectExpression)expr).setFieldDefinition(m.getFieldMetaData().getName(), m.getFieldMetaData().getTypeName());
                    }
                    return expr;
                }
                else
                {
                    // Field of main table
                    m = ct.getFieldMapping(fieldName);
                    if (m == null)
                    {
                        throw new JPOXUserException(LOCALISER.msg("037001", fieldName, ct.toString()));
                    }

                    ScalarExpression expr = m.newScalarExpression(qs, this);
                    if (expr instanceof ObjectExpression)
                    {
                        ((ObjectExpression)expr).setFieldDefinition(fieldName, m.getType());
                    }
                    return expr;
                }
            }
        }
        else if (mainTable instanceof DatastoreCollection ||
                 mainTable instanceof DatastoreMap)
        {
            // User has an embedded element/key/value and has a constraint on it
            String fld = fieldName;
            if (fieldName.indexOf(".") > 0)
            {
                // TODO Process the base field - typically is "null". When is it not "null" ?
                String subField = fieldName.substring(fieldName.indexOf(".")+1);
                fld = subField;
            }

            if (mainTable instanceof DatastoreElementContainer)
            {
                // collection/array - element mapping
                DatastoreElementContainer join = (DatastoreElementContainer)mainTable;
                JavaTypeMapping m = join.getElementMapping();
                if (m instanceof EmbeddedElementPCMapping)
                {
                    JavaTypeMapping fieldMapping = ((EmbeddedMapping)m).getJavaTypeMapping(fld);
                    if (fieldMapping != null)
                    {
                        return fieldMapping.newScalarExpression(qs, this);
                    }
                    else
                    {
                        throw new JPOXUserException("'" + fieldName + "' was not found as a field stored in the join table " + mainTable);
                    }
                }
            }
            else if (mainTable instanceof DatastoreMap)
            {
                // Check for a key field first
                DatastoreMap join = (DatastoreMap)mainTable;
                JavaTypeMapping m = join.getKeyMapping();
                if (m instanceof EmbeddedKeyPCMapping)
                {
                    JavaTypeMapping fieldMapping = ((EmbeddedMapping)m).getJavaTypeMapping(fld);
                    if (fieldMapping != null)
                    {
                        return fieldMapping.newScalarExpression(qs, this);
                    }
                }

                // Check for a value field next
                m = join.getValueMapping();
                if (m instanceof EmbeddedValuePCMapping)
                {
                    JavaTypeMapping fieldMapping = ((EmbeddedMapping)m).getJavaTypeMapping(fld);
                    if (fieldMapping != null)
                    {
                        return fieldMapping.newScalarExpression(qs, this);
                    }
                }
            }

            throw new JPOXUserException("'" + fieldName + "' was not found as an embedded element/key/value field stored in the join table " + mainTable);
        }
        else
        {
            throw new JPOXUserException("'" + fieldName + "' can't be referenced in " +
                   mainTable.toString() + ": table does not store a persistence-capable class or a join table storing a persistence-capable class");
        }
    }

    /**
     * Convenience method to find the JavaTypeMapping for an embedded field.
     * @param m The embedded field mapping
     * @param fieldName The field name to find
     * @return The JavaTypeMapping for the (embedded) field
     */
    private JavaTypeMapping getMappingForEmbeddedField(EmbeddedPCMapping m, String fieldName)
    {
        if (m == null || fieldName == null)
        {
            return null;
        }

        if (fieldName.indexOf(".") < 0)
        {
            return m.getJavaTypeMapping(fieldName);
        }

        String field = fieldName.substring(0, fieldName.indexOf("."));
        String subField = fieldName.substring(fieldName.indexOf(".")+1);
        JavaTypeMapping mapping = m.getJavaTypeMapping(field);
        if (mapping instanceof EmbeddedPCMapping && subField != null)
        {
            return getMappingForEmbeddedField((EmbeddedPCMapping)mapping, subField);
        }
        return mapping;
    }

    /**
     * Return an identifier/reference to the datastore field/column.
     * @param col the column to have a reference
     * @return identifier or fully qualified identifier
     */
    public abstract String referenceColumn(DatastoreField col);

    public abstract String toString();
   
    public int hashCode()
    {
        return mainTable.hashCode() ^ mainAlias.hashCode();
    }
   
    public boolean equals(Object obj)
    {
        if( obj == this )
        {
            return true;
        }
        if( obj == null )
        {
            return false;
        }
        if( !(obj instanceof LogicSetExpression) )
        {
            return false;
        }
        LogicSetExpression expr = (LogicSetExpression) obj;
        return this.mainAlias.equals(expr.mainAlias) && this.mainTable.equals(expr.mainTable);
    }
}
TOP

Related Classes of org.jpox.store.mapped.expression.LogicSetExpression

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.