Qt 4.8
Protected Functions | Private Functions | Static Private Functions | Properties | List of all members
QPatternist::CastingPlatform< TSubClass, issueError > Class Template Reference

Provides casting functionality for classes, such as CastAs or NumberFN, which needs to perform casting. More...

#include <qcastingplatform_p.h>

Protected Functions

Item cast (const Item &sourceValue, const ReportContext::Ptr &context) const
 
 CastingPlatform (const ReportContext::ErrorCode code=ReportContext::FORG0001)
 
void checkTargetType (const ReportContext::Ptr &context) const
 
bool prepareCasting (const ReportContext::Ptr &context, const ItemType::Ptr &sourceType)
 

Private Functions

Item castWithCaster (const Item &sourceValue, const AtomicCaster::Ptr &caster, const ReportContext::Ptr &context) const
 
Item castWithCaster (const Item &sourceValue, const AtomicCaster::Ptr &caster, const DynamicContext::Ptr &context) const
 
void issueCastError (const Item &validationError, const Item &sourceValue, const ReportContext::Ptr &context) const
 
ItemType::Ptr targetType () const
 

Static Private Functions

static AtomicCaster::Ptr locateCaster (const ItemType::Ptr &sourceType, const ReportContext::Ptr &context, bool &castImpossible, const SourceLocationReflection *const location, const ItemType::Ptr &targetType)
 

Properties

AtomicCaster::Ptr m_caster
 
const ReportContext::ErrorCode m_errorCode
 

Detailed Description

template<typename TSubClass, const bool issueError>
class QPatternist::CastingPlatform< TSubClass, issueError >

Provides casting functionality for classes, such as CastAs or NumberFN, which needs to perform casting.

Classes which need to perform casting can simply from this class and gain access to casting functinality wrapped in a convenient way. At the center of this class is the cast() function, which is used at runtime to perform the actual cast.

The actual circumstances where casting is used, such as in the 'castable as' expression or the fn:number() function, often have other things to handle as well, error handling and cardinality checks for example. This class handles only casting and leaves the other case-specific details to the sub-class such that this class only do one thing well.

This template class takes two parameters:

The class inheriting CastingPlatform must implement the following function:

that returns the type that should be cast to. The type must be an AtomicType. Typically, it is appropriate to declare this function inline.

A sub-class calls prepareCasting() at compile time(such that CastingPlatform can attempt to lookup the proper AtomicCaster) and then it simply uses the cast() function at runtime. The function targetType() must be implemented such that CastingPlatform knows what type it shall cast to.

See also
ValueFactory
Author
Frans Englich frans.nosp@m..eng.nosp@m.lich@.nosp@m.noki.nosp@m.a.com

Definition at line 110 of file qcastingplatform_p.h.

Constructors and Destructors

◆ CastingPlatform()

template<typename TSubClass, const bool issueError>
QPatternist::CastingPlatform< TSubClass, issueError >::CastingPlatform ( const ReportContext::ErrorCode  code = ReportContext::FORG0001)
inlineprotected
Note
issueCastError() depends on the default value.

Definition at line 116 of file qcastingplatform_p.h.

116  : m_errorCode(code)
117  {
118  }
const ReportContext::ErrorCode m_errorCode

Functions

◆ cast()

template<typename TSubClass , const bool issueError>
Item QPatternist::CastingPlatform< TSubClass, issueError >::cast ( const Item sourceValue,
const ReportContext::Ptr context 
) const
protected

Attempts to cast sourceValue to targetType(), and returns the created value. Remember that prepareCasting() should have been called at compile time, otherwise this function will be slow.

Error reporting is done in two ways. If a cast fails because of an error in lexical representation a ValidationError is returned. If the cause of failure is that the casting combination is invalid(such as when attempting to cast xs:date to xs:integer), a ValidationError is returned if false was passed in the template instantiation, an error is issued via context.

Parameters
sourceValuethe value to cast. Must be non null.
contextthe usual ReportContext, used for error reporting.
Returns
the new value which was the result of the cast. If the cast failed, an ValidationError is returned.

Definition at line 74 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform().

76 {
77  Q_ASSERT(sourceValue);
78  Q_ASSERT(context);
80 
81  if(m_caster)
82  return castWithCaster(sourceValue, m_caster, context);
83  else
84  {
85  bool castImpossible = false;
86  const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible, static_cast<const TSubClass *>(this), targetType()));
87 
88  if(!issueError && castImpossible)
89  {
90  /* If we're supposed to issue an error(issueError) then this
91  * line will never be reached, because locateCaster() will in
92  * that case throw. */
94  }
95  else
96  return castWithCaster(sourceValue, caster, context);
97  }
98 }
static AtomicValue::Ptr createError(const QString &description=QString(), const ReportContext::ErrorCode=ReportContext::FORG0001)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
ItemType::Ptr targetType() const
Item castWithCaster(const Item &sourceValue, const AtomicCaster::Ptr &caster, const ReportContext::Ptr &context) const
static AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, const ReportContext::Ptr &context, bool &castImpossible, const SourceLocationReflection *const location, const ItemType::Ptr &targetType)
QExplicitlySharedDataPointer< AtomicCaster > Ptr

◆ castWithCaster() [1/2]

template<typename TSubClass , const bool issueError>
Item QPatternist::CastingPlatform< TSubClass, issueError >::castWithCaster ( const Item sourceValue,
const AtomicCaster::Ptr caster,
const ReportContext::Ptr context 
) const
inlineprivate

Definition at line 49 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform().

52 {
53  Q_ASSERT(sourceValue);
54  Q_ASSERT(caster);
55  Q_ASSERT(context);
56 
57  const Item retval(caster->castFrom(sourceValue, context));
58 
59  if(issueError)
60  {
61  if(retval.template as<AtomicValue>()->hasError())
62  {
63  issueCastError(retval, sourceValue, context);
64  return Item();
65  }
66  else
67  return retval;
68  }
69  else
70  return retval;
71 }
void issueCastError(const Item &validationError, const Item &sourceValue, const ReportContext::Ptr &context) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The Item is the most basic of all visual items in QML.

◆ castWithCaster() [2/2]

template<typename TSubClass, const bool issueError>
Item QPatternist::CastingPlatform< TSubClass, issueError >::castWithCaster ( const Item sourceValue,
const AtomicCaster::Ptr caster,
const DynamicContext::Ptr context 
) const
inlineprivate

◆ checkTargetType()

template<typename TSubClass , const bool issueError>
void QPatternist::CastingPlatform< TSubClass, issueError >::checkTargetType ( const ReportContext::Ptr context) const
protected

Checks that the targetType() is a valid target type for castable as and cast as. For example, that it is not abstract. If the type is invalid, an error is raised via the context. Note that it is assumed the type is atomic.

Definition at line 166 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform().

167 {
168  Q_ASSERT(context);
169 
170  const ItemType::Ptr tType(targetType());
171  Q_ASSERT(tType);
172  Q_ASSERT(tType->isAtomicType());
173  const AtomicType::Ptr asAtomic(tType);
174 
175  /* This catches casting to xs:NOTATION and xs:anyAtomicType. */
176  if(asAtomic->isAbstract())
177  {
178  context->error(QtXmlPatterns::tr("Casting to %1 is not possible because it "
179  "is an abstract type, and can therefore never be instantiated.")
180  .arg(formatType(context->namePool(), tType)),
182  static_cast<const TSubClass*>(this));
183  }
184 }
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
QExplicitlySharedDataPointer< AtomicType > Ptr
Definition: qatomictype_p.h:85
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
ItemType::Ptr targetType() const
QExplicitlySharedDataPointer< ItemType > Ptr
Definition: qitemtype_p.h:88

◆ issueCastError()

template<typename TSubClass , const bool issueError>
void QPatternist::CastingPlatform< TSubClass, issueError >::issueCastError ( const Item validationError,
const Item sourceValue,
const ReportContext::Ptr context 
) const
private

Definition at line 187 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::targetType().

190 {
191  Q_ASSERT(validationError);
192  Q_ASSERT(context);
193  Q_ASSERT(validationError.isAtomicValue());
194  Q_ASSERT(validationError.template as<AtomicValue>()->hasError());
195 
196  const ValidationError::Ptr err(validationError.template as<ValidationError>());
197  QString msg(err->message());
198 
199  if(msg.isNull())
200  {
201  msg = QtXmlPatterns::tr("It's not possible to cast the value %1 of type %2 to %3")
202  .arg(formatData(sourceValue.stringValue()))
203  .arg(formatType(context->namePool(), sourceValue.type()))
204  .arg(formatType(context->namePool(), targetType()));
205  }
206  else
207  {
208  Q_ASSERT(!msg.isEmpty());
209  msg = QtXmlPatterns::tr("Failure when casting from %1 to %2: %3")
210  .arg(formatType(context->namePool(), sourceValue.type()))
211  .arg(formatType(context->namePool(), targetType()))
212  .arg(msg);
213  }
214 
215  /* If m_errorCode is FORG0001, we assume our sub-classer doesn't have a
216  * special wish about error code, so then we use the error object's code.
217  */
218  context->error(msg, m_errorCode == ReportContext::FORG0001 ? err->errorCode() : m_errorCode,
219  static_cast<const TSubClass*>(this));
220 }
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static QString formatData(const QString &data)
ItemType::Ptr targetType() const
QExplicitlySharedDataPointer< ValidationError > Ptr
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
const ReportContext::ErrorCode m_errorCode

◆ locateCaster()

template<typename TSubClass , const bool issueError>
AtomicCaster::Ptr QPatternist::CastingPlatform< TSubClass, issueError >::locateCaster ( const ItemType::Ptr sourceType,
const ReportContext::Ptr context,
bool &  castImpossible,
const SourceLocationReflection *const  location,
const ItemType::Ptr targetType 
)
staticprivate

Locates the caster for casting values of type sourceType to targetType(), if possible.

castImpossible is not initialized. Initialize it to false.

Definition at line 121 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform().

126 {
127  Q_ASSERT(sourceType);
129 
130  const AtomicCasterLocator::Ptr locator(static_cast<AtomicType *>(
131  targetType.data())->casterLocator());
132  if(!locator)
133  {
134  if(issueError)
135  {
136  context->error(QtXmlPatterns::tr("No casting is possible with %1 as the target type.")
137  .arg(formatType(context->namePool(), targetType)),
139  }
140  else
141  castImpossible = true;
142 
143  return AtomicCaster::Ptr();
144  }
145 
146  const AtomicCaster::Ptr caster(static_cast<const AtomicType *>(sourceType.data())->accept(locator, location));
147  if(!caster)
148  {
149  if(issueError)
150  {
151  context->error(QtXmlPatterns::tr("It is not possible to cast from %1 to %2.")
152  .arg(formatType(context->namePool(), sourceType))
153  .arg(formatType(context->namePool(), targetType)),
155  }
156  else
157  castImpossible = true;
158 
159  return AtomicCaster::Ptr();
160  }
161 
162  return caster;
163 }
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QExplicitlySharedDataPointer< AtomicCasterLocator > Ptr
T * data() const
Returns a pointer to the shared data object.
Definition: qshareddata.h:145
ItemType::Ptr targetType() const
static QTestResult::TestLocation location
Definition: qtestresult.cpp:63
QExplicitlySharedDataPointer< AtomicCaster > Ptr

◆ prepareCasting()

template<typename TSubClass , const bool issueError>
bool QPatternist::CastingPlatform< TSubClass, issueError >::prepareCasting ( const ReportContext::Ptr context,
const ItemType::Ptr sourceType 
)
protected

This function should be called at compiled time, it attempts to determine what AtomicCaster that should be used when casting from sourceType to targetType(). If that is not possible, because the sourceType is xs:anyAtomicType for instance, the AtomicCaster lookup will done at runtime on a case-per-case basis.

Returns
true if the requested casting combination is valid or might be valid. If it is guranteed to be invalid, false is returned.

Definition at line 101 of file qcastingplatform.cpp.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform().

103 {
104  Q_ASSERT(sourceType);
105  Q_ASSERT(context);
106 
107  if(*sourceType == *BuiltinTypes::xsAnyAtomicType ||
108  *sourceType == *BuiltinTypes::item ||
109  *sourceType == *CommonSequenceTypes::Empty ||
110  *sourceType == *BuiltinTypes::numeric)
111  return true; /* The type could not be narrowed better than xs:anyAtomicType
112  or numeric at compile time. We'll do lookup at runtime instead. */
113 
114  bool castImpossible = false;
115  m_caster = locateCaster(sourceType, context, castImpossible, static_cast<const TSubClass *>(this), targetType());
116 
117  return !castImpossible;
118 }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static const ItemType::Ptr item
ItemType::Ptr targetType() const
static const EmptySequenceType::Ptr Empty
static const AtomicType::Ptr numeric
static const AtomicType::Ptr xsAnyAtomicType
static AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, const ReportContext::Ptr &context, bool &castImpossible, const SourceLocationReflection *const location, const ItemType::Ptr &targetType)

◆ targetType()

template<typename TSubClass, const bool issueError>
ItemType::Ptr QPatternist::CastingPlatform< TSubClass, issueError >::targetType ( ) const
inlineprivate

Definition at line 183 of file qcastingplatform_p.h.

Referenced by QPatternist::CastingPlatform< UntypedAtomicConverter, true >::CastingPlatform(), and QPatternist::CastingPlatform< UntypedAtomicConverter, true >::targetType().

184  {
185  Q_ASSERT(static_cast<const TSubClass *>(this)->targetType());
186  return static_cast<const TSubClass *>(this)->targetType();
187  }
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
ItemType::Ptr targetType() const

Properties

◆ m_caster

template<typename TSubClass, const bool issueError>
AtomicCaster::Ptr QPatternist::CastingPlatform< TSubClass, issueError >::m_caster
private

Definition at line 194 of file qcastingplatform_p.h.

◆ m_errorCode

template<typename TSubClass, const bool issueError>
const ReportContext::ErrorCode QPatternist::CastingPlatform< TSubClass, issueError >::m_errorCode
private

Definition at line 195 of file qcastingplatform_p.h.


The documentation for this class was generated from the following files: