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

org.datanucleus.store.rdbms.table.ClassView Maven / Gradle / Ivy

/**********************************************************************
Copyright (c) 2002 Kelly Grizzle (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 Andy Jefferson - replaced TableMetadata with identifier and java name
2003 Andy Jefferson - coding standards
2004 Andy Jefferson - merged with JDOView
2004 Andy Jefferson - split out CorrespondentColumnsMapping
2005 Andy Jefferson - reworked to implement DatastoreClass and generate mappings correctly
    ...
**********************************************************************/
package org.datanucleus.store.rdbms.table;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.ClassMetaData;
import org.datanucleus.metadata.DiscriminatorMetaData;
import org.datanucleus.metadata.FieldPersistenceModifier;
import org.datanucleus.metadata.FieldRole;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.metadata.MetaData;
import org.datanucleus.metadata.VersionMetaData;
import org.datanucleus.store.rdbms.exceptions.NoSuchPersistentFieldException;
import org.datanucleus.store.rdbms.RDBMSStoreManager;
import org.datanucleus.store.rdbms.exceptions.PersistentSuperclassNotAllowedException;
import org.datanucleus.store.rdbms.exceptions.ViewDefinitionException;
import org.datanucleus.store.rdbms.identifier.DatastoreIdentifier;
import org.datanucleus.store.rdbms.mapping.MappingConsumer;
import org.datanucleus.store.rdbms.mapping.MappingType;
import org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping;
import org.datanucleus.store.schema.table.SurrogateColumnType;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.MacroString;
import org.datanucleus.util.NucleusLogger;

/**
 * Representation of an SQL View for a Class.
 * Requires that the class use "nondurable" identity.
 * Since a view is read-only, many methods throw exceptions that the operation is
 * not supported.
 */
public class ClassView extends ViewImpl implements DatastoreClass
{
    /** Class MetaData for the class mapping to this view. */
    private final ClassMetaData cmd;

    /** Definition of the view. */
    private final MacroString viewDef;

    /** DDL statement for creating the view **/
    private String createStatementDDL;
    
    /** Mappings for the fields of this class to map to the View. */
    private JavaTypeMapping[] fieldMappings;

    /**
     * Constructor for class view.
     * @param tableName The name of the view.
     * @param storeMgr The RDBMS manager managing this view
     * @param cmd The metadata for the class represented by this view.
     */
    public ClassView(final DatastoreIdentifier tableName, final RDBMSStoreManager storeMgr, final ClassMetaData cmd)
    {
        super(tableName, storeMgr);
        this.cmd = cmd;

        if (cmd.getIdentityType() == IdentityType.APPLICATION || cmd.getIdentityType() == IdentityType.DATASTORE)
        {
            // In all version until 5.1.0.M3 this required NONDURABLE to continue here
            NucleusLogger.DATASTORE_SCHEMA.debug("Mapping VIEW " + tableName + " to class " + cmd.getFullClassName() + " which uses " + cmd.getIdentityType());
        }

        // We expect a flat class here to map to a view.
        if (cmd.getPersistableSuperclass() != null)
        {
            throw new PersistentSuperclassNotAllowedException(cmd.getFullClassName());
        }

        // Extract the view definition from MetaData
        String viewImpStr = cmd.getValueForExtension(MetaData.EXTENSION_CLASS_VIEW_IMPORTS);
        String viewDefStr = null;
        if (dba.getVendorID() != null)
        {
            viewDefStr = cmd.getValueForExtension(MetaData.EXTENSION_CLASS_VIEW_DEFINITION + '-' + dba.getVendorID());
        }
        if (viewDefStr == null)
        {
            viewDefStr = cmd.getValueForExtension(MetaData.EXTENSION_CLASS_VIEW_DEFINITION);
        }
        if (viewDefStr == null)
        {
            throw new ViewDefinitionException(cmd.getFullClassName(), null);
        }

        viewDef = new MacroString(cmd.getFullClassName(), viewImpStr, viewDefStr);
    }
   
    /**
     * Method to initialise the view. Generates the mappings for all fields in
     * the class to map to this view.
     * @param clr The ClassLoaderResolver
     */
    @Override
    public void initialize(final ClassLoaderResolver clr)
    {
        assertIsUninitialized();

        int fieldCount = cmd.getNoOfManagedMembers();
        fieldMappings = new JavaTypeMapping[fieldCount];
        for (int fieldNumber = 0; fieldNumber < fieldCount; ++fieldNumber)
        {
            AbstractMemberMetaData fmd = cmd.getMetaDataForManagedMemberAtRelativePosition(fieldNumber);
            if (fmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT)
            {
                fieldMappings[fieldNumber] = storeMgr.getMappingManager().getMapping(this, fmd, clr, FieldRole.ROLE_FIELD);
            }
            else if (fmd.getPersistenceModifier() != FieldPersistenceModifier.TRANSACTIONAL)
            {
                throw new NucleusException(Localiser.msg("031006", cmd.getFullClassName(), fmd.getName(), fmd.getPersistenceModifier())).setFatal();
            }
        }

        if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
        {
            NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
        }
        storeMgr.registerTableInitialized(this);
        state = TABLE_STATE_INITIALIZED;
    }

    /**
     * Post initialise. For things that must be set after all classes have been initialised before.
     * @param clr the ClassLoaderResolver
     */
    @Override
    public void postInitialize(final ClassLoaderResolver clr)
    {
        assertIsInitialized();

        createStatementDDL = viewDef.substituteMacros(new MacroString.MacroHandler()
            {
                public void onIdentifierMacro(MacroString.IdentifierMacro im)
                {
                    storeMgr.resolveIdentifierMacro(im, clr);
                }

                public void onParameterMacro(MacroString.ParameterMacro pm)
                {
                    throw new NucleusUserException(Localiser.msg("031009", cmd.getFullClassName(), pm));
                }
            }, clr
        );
    }

    /**
     * Accessor for a mapping for the ID. A view row doesn't have an id as such.
     * @return The ID mapping.
     */
    public JavaTypeMapping getIdMapping()
    {
        // Just return the first mapping that we have (since we have no "id" and this is used for "count(this)" queries so doesnt matter)
        // If there are other situations that would come through here then we would need to cater for those better
        for (int i=0;i getSQLCreateStatements(Properties props)
    {
        assertIsInitialized();

        List stmts = new ArrayList<>();
        StringTokenizer tokens = new StringTokenizer(createStatementDDL, ";");

        while (tokens.hasMoreTokens())
        {
            String token = tokens.nextToken();
            if (token.startsWith("--"))
            {
                // Ignore comment lines because some RDBMS will not handle these
                continue;
            }
            stmts.add(token);
        }

        return stmts;
    }

    /* (non-Javadoc)
     * @see org.datanucleus.store.schema.table.Table#getSurrogateColumn(org.datanucleus.store.schema.table.SurrogateColumnType)
     */
    @Override
    public Column getSurrogateColumn(SurrogateColumnType colType)
    {
        // No surrogate columns on a view
        return null;
    }

    /**
     * Accessor for Discriminator MetaData
     * @return Returns the Discriminator MetaData.
     */
    public final DiscriminatorMetaData getDiscriminatorMetaData()
    {
        return null; // No discriminators for Views
    }

    /**
     * Accessor for Version MetaData
     * @return Returns the Version MetaData.
     */
    public final VersionMetaData getVersionMetaData()
    {
        return null; // No versions for Views
    }

    public JavaTypeMapping getExternalMapping(AbstractMemberMetaData mmd, MappingType mappingType)
    {
        // We do not support "external mappings" with a view. The mapping must be present in the view definition
        return null;
    }

    public AbstractMemberMetaData getMetaDataForExternalMapping(JavaTypeMapping mapping, MappingType mappingType)
    {
        // We do not support "external mappings" with a view. The mapping must be present in the view definition
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy