const CItemInfo* CItemsInfo::FindNextMandatory(const CItemInfo* info) { if (!info->GetId().HasNotag()) { const CMemberInfo* mem = dynamic_cast<const CMemberInfo*>(info); if (mem && mem->Optional()) { return 0; } return info; } const CItemInfo* found = 0; TTypeInfo type = FindRealTypeInfo(info->GetTypeInfo()); ETypeFamily family = type->GetTypeFamily(); if (family == eTypeFamilyClass || family == eTypeFamilyChoice) { const CClassTypeInfoBase* classType = dynamic_cast<const CClassTypeInfoBase*>(type); _ASSERT(classType); const CItemsInfo& items = classType->GetItems(); TMemberIndex i; const CItemInfo* found_first = 0; for (i = items.FirstIndex(); i <= items.LastIndex(); ++i) { const CItemInfo* item = classType->GetItems().GetItemInfo(i); ETypeFamily item_family = item->GetTypeInfo()->GetTypeFamily(); if (item_family == eTypeFamilyPointer) { const CPointerTypeInfo* ptr = dynamic_cast<const CPointerTypeInfo*>(item->GetTypeInfo()); if (ptr) { item_family = ptr->GetPointedType()->GetTypeFamily(); } } if (item_family == eTypeFamilyContainer) { if (item->NonEmpty()) { found = FindNextMandatory( item ); } } else { found = FindNextMandatory( item ); } if (family == eTypeFamilyClass) { if (found) { return found; } } else { if (!found) { // this is optional choice variant return 0; } if (!found_first) { found_first = found; } } } return found_first; } return found; }
void CChoicePointerTypeInfo::SetPointerType(TTypeInfo base) { m_NullPointerIndex = kEmptyChoice; if ( base->GetTypeFamily() != eTypeFamilyPointer ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument: must be CPointerTypeInfo"); const CPointerTypeInfo* ptrType = CTypeConverter<CPointerTypeInfo>::SafeCast(base); m_PointerTypeInfo = ptrType; if ( ptrType->GetPointedType()->GetTypeFamily() != eTypeFamilyClass ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument: data must be CClassTypeInfo"); const CClassTypeInfo* classType = CTypeConverter<CClassTypeInfo>::SafeCast(ptrType->GetPointedType()); /* Do we really need it to be CObject??? if ( !classType->IsCObject() ) NCBI_THROW(CSerialException,eInvalidData, "invalid argument:: choice ptr type must be CObject"); */ const CClassTypeInfo::TSubClasses* subclasses = classType->SubClasses(); if ( !subclasses ) return; TTypeInfo nullTypeInfo = CNullTypeInfo::GetTypeInfo(); for ( CClassTypeInfo::TSubClasses::const_iterator i = subclasses->begin(); i != subclasses->end(); ++i ) { TTypeInfo variantType = i->second.Get(); if ( !variantType ) { // null variantType = nullTypeInfo; } AddVariant(i->first, 0, variantType)->SetSubClass(); TMemberIndex index = GetVariants().LastIndex(); if ( variantType == nullTypeInfo ) { if ( m_NullPointerIndex == kEmptyChoice ) m_NullPointerIndex = index; else { ERR_POST_X(1, "double null"); } } else { const type_info* id = &CTypeConverter<CClassTypeInfo>::SafeCast(variantType)->GetId(); if ( !m_VariantsByType.insert(TVariantsByType::value_type(id, index)).second ) { NCBI_THROW(CSerialException,eInvalidData, "conflict subclasses: "+variantType->GetName()); } } } }