(file) Return to CQLChainedIdentifierRep.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / CQL

File: [Pegasus] / pegasus / src / Pegasus / CQL / CQLChainedIdentifierRep.cpp (download)
Revision: 1.1.2.18, Thu Nov 4 18:04:05 2004 UTC (19 years, 8 months ago) by humberto
Branch: CQL_2_5_BRANCH
Changes since 1.1.2.17: +9 -1 lines
PEP#: 193

TITLE: CQL Stage 1

DESCRIPTION: CQL implementation

//%2003////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
// IBM Corp.; EMC Corporation, The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Authors: David Rosckes (rosckes@us.ibm.com)
//          Bert Rivero (hurivero@us.ibm.com)
//          Chuck Carmack (carmack@us.ibm.com)
//          Brian Lucier (lucier@us.ibm.com)
//
// Modified By: 
//
//%/////////////////////////////////////////////////////////////////////////////

#include "CQLChainedIdentifier.h"
#include "CQLChainedIdentifierRep.h"
#include <Pegasus/CQL/CQLFactory.h>
#include <Pegasus/CQL/QueryContext.h>
#include "QueryException.h"

PEGASUS_NAMESPACE_BEGIN

CQLChainedIdentifierRep::CQLChainedIdentifierRep(){
}

CQLChainedIdentifierRep::CQLChainedIdentifierRep(String inString)
{
	parse(inString);
}

CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLIdentifier &id)
{
        _subIdentifiers.append(id);
}

CQLChainedIdentifierRep::CQLChainedIdentifierRep(const CQLChainedIdentifierRep* rep){
	_subIdentifiers = rep->_subIdentifiers;
}

CQLChainedIdentifierRep::~CQLChainedIdentifierRep(){
	
}

const Array<CQLIdentifier>& CQLChainedIdentifierRep::getSubIdentifiers()const
{
	return _subIdentifiers;
}

CQLIdentifier CQLChainedIdentifierRep::getLastIdentifier()const{
	if(_subIdentifiers.size() > 0)
		return _subIdentifiers[_subIdentifiers.size()-1];
	return CQLIdentifier();
}

String CQLChainedIdentifierRep::toString()const{
	String s;
	for(Uint32 i = 0; i < _subIdentifiers.size(); i++){
		s.append(_subIdentifiers[i].toString());
		if(i < _subIdentifiers.size() - 1)
			s.append(".");
	}
	return s;
}

void CQLChainedIdentifierRep::append(const CQLIdentifier & id){
	_subIdentifiers.append(id);
}

Boolean CQLChainedIdentifierRep::isSubChain(const CQLChainedIdentifier & chain)const{
	Array<CQLIdentifier> ids = chain.getSubIdentifiers();
	for(Uint32 i = 0; i < ids.size(); i++){
		if(ids[i] != _subIdentifiers[i].getName())
			return false;
	}
	return true;
}

CQLIdentifier CQLChainedIdentifierRep::operator[](Uint32 index)const
{
	return CQLIdentifier(_subIdentifiers[index]);
}

CQLChainedIdentifierRep& CQLChainedIdentifierRep::operator=(const CQLChainedIdentifierRep& rhs){
	if(&rhs != this){
		_subIdentifiers = rhs._subIdentifiers;
	}
	return *this;
}

Uint32 CQLChainedIdentifierRep::size()const{
	return _subIdentifiers.size();
}

Boolean CQLChainedIdentifierRep::prepend(const CQLIdentifier & id){
	/*
	   Compare id against the first element in _subIdentifiers, 
	   if not an exact match, then prepend.  This is used to fully
	   qualify the chained identifier.
	*/
	if(id != _subIdentifiers[0]){
		_subIdentifiers.prepend(id);
		return true;
	}
	return false;
}

void CQLChainedIdentifierRep::applyContext(QueryContext& inContext)
{
  if (_subIdentifiers.size() == 0)
    return;

  // Chained identifiers that are standalone symbolic constants 
  // should have had the context applied already.  If this method
  // is called and this is still a standalone symbolic constant,
  // then that is an error.
  if (_subIdentifiers.size() == 1 &&
      _subIdentifiers[0].getName().getString().size() == 0 &&
      _subIdentifiers[0].isSymbolicConstant())
  {
    throw CQLValidationException(
                                        MessageLoaderParms(String("CQL.CQLChainedIdentifier.STAND_ALONE_SYMBOLIC_CONSTANT"),
                                                           String("The stand alone chained identifier should have had the context applied already."))
                                         );
  }

  CQLIdentifier firstId = _subIdentifiers[0];
  
  // Process if the first identifier has some contents.
  if ((firstId.getName().getString().size() != 0) || firstId.isWildcard()) 
  {
    Array<CQLIdentifier> fromList = inContext.getFromList();

    if (firstId.isWildcard())
    {
      // First chain element is wildcarded.
      // Prepend the FROM class.
      _subIdentifiers.prepend(fromList[0]);
    }  
    else
    {
      // Not a wildcard.
      if (firstId.isScoped())
      {
        // The first identifier is a scoped property or a 
        // scoped symbolic constant.
        // Prepend the FROM class.
        // Example: SELECT * FROM F WHERE someprop = X::p#'OK'
	_subIdentifiers.prepend(fromList[0]);
      }
      else
      {
        // The first identifier is not a scoped property or a scoped
        // symbolic constant.

        // Determine if the first identifier's name is in the FROM list.
	String classContext = firstId.getName().getString();
	CQLIdentifier matchedId = inContext.findClass(classContext);
	if (matchedId.getName().getString().size() == 0)
	{
	  // Could not find the firstId in the FROM list.
	  // Assume the firstId is a property on the FROM class.
          // Prepend the FROM class, except in the cases described below.
          //
          // NOTE:
          // We need special handling for symbolic constants, because there are cases
          // where the first id is a class that is not the FROM class.
          // Refer to section 5.4.3 of the CQL spec.
          //
          // Examples:
          // SELECT * FROM F WHERE F.someprop = prop#'OK'
          // Prepend the FROM class because symbolic constants can only
          // apply to properties, and properties in the first position
          // are assumed to be on the FROM class.
          //
          // SELECT * FROM F WHERE F.someprop = ClassNotInFromList.prop#'OK'
          // We don't want to prepend the FROM class to ClassNotInFromList 
          // in this case. But we need to get the FROM class from the schema
          // to make sure ClassNotInFromList is not a property on the FROM class. 
          //
          // SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p#'OK'
          // In this case embeddedObjectOnF is an embedded object property
          // on the FROM class.  We want to prepend the FROM class.  But
          // we need to get FROM class from the schema first to make sure.
          //
          // SELECT * FROM F WHERE F.someprop = embeddedObjectOnF.X::p
          // In this case embeddedObjectOnF is an embedded object property
          // on the FROM class.  We want to prepend the FROM class.  Since
          // the last id is not a symbolic constant we can prepend without
          // getting the FROM class from the schema.
          //
          // Note that standalone symbolic constants, like #'OK'
          // are errors when this code is run.
          // See above for details.
          //

          if (firstId.isSymbolicConstant() ||
              !getLastIdentifier().isSymbolicConstant()) 
          {
            // Must be a property on the FROM class.
	    _subIdentifiers.prepend(fromList[0]);            
          }
          else
          {
            // Get the FROM class. 
            try
            {
              CIMClass fromClass = inContext.getClass(fromList[0].getName());
              if (fromClass.findProperty(firstId.getName()) != PEG_NOT_FOUND)
              {
                // A property on the FROM class.
                _subIdentifiers.prepend(fromList[0]);                              
              }
            }
            catch (CIMException& ce)
            {
              if (ce.getCode() == CIM_ERR_INVALID_CLASS || 
                  ce.getCode() == CIM_ERR_NOT_FOUND)
              {
                // ATTN may just want to throw the CIMException rather than
                // CQL exception
                throw Exception("TEMP MSG - CQLChainId::applyContext - FROM class does not exist");
		throw CQLValidationException(
                                        MessageLoaderParms(String("CQL.CQLChainedIdentifier.FROM_CLASS_DOES_NOT_EXIST"),
                                                           String("The FROM class does not exist while applying context."))
                                         );
              }
            }
          }
	}
	else
	{	
	  // The firstId was found in the FROM list, but it could have been 
	  // an alias
	  if (!matchedId.getName().equal(firstId.getName()))
	  {
	    // It was an alias.
	    // Replace the alias with the FROM class
	    _subIdentifiers[0] = matchedId;
	  }
	  else 
	  {
	    // It was not an alias. Do nothing.
	    ;
	  }
	}
      }
    }
  }
  
  // Go through and replace any aliases on scoping classes
  for (Uint32 i = 0; i < _subIdentifiers.size(); i++)
  {
    if (_subIdentifiers[i].isScoped())
    {
      CQLIdentifier match = inContext.findClass(_subIdentifiers[i].getScope());
      if (match.getName().getString().size() != 0)
      {
        // The scoping class was either the FROM class, or an alias of the
        // FROM class.  Replace the scoping class with the FROM class.
	_subIdentifiers[i].applyScope(match.getName().getString());
      }
    }
  }
}

void CQLChainedIdentifierRep::parse(String & string){
	/* 
	  - parse string on "."
	  - start from the end of string
	  - if more than one substring found, 
		-- store first found string then
		-- prepend remaining substrings 
	*/
	Char16 delim('.');
	Uint32 index;
	String range;

	/* remove any array ranges so we dont parse a false . */
	if((index = string.find("[")) != PEG_NOT_FOUND){
		range = string.subString(index);
		string.remove(index);
	}

	index = string.reverseFind(delim);
	if(index == PEG_NOT_FOUND){
		/* append the range we may have removed */
		string.append(range);
		_subIdentifiers.append(CQLIdentifier(string));
	}else{
		/* append the range we may have removed */
		String tmp = string.subString(index+1);
		tmp.append(range);
		_subIdentifiers.append(CQLIdentifier(tmp));

		while(index != PEG_NOT_FOUND){
			tmp = string.subString(0,index);
			index = tmp.reverseFind(delim);
			if(index == PEG_NOT_FOUND){
				_subIdentifiers.prepend(CQLIdentifier(tmp));
			}
			else{
				_subIdentifiers.prepend(CQLIdentifier(tmp.subString(index+1)));
			}
		}
	}
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2