00001 #ifndef IGUANA_IG_FILE_IG_COLLECTION_H
00002 #define IGUANA_IG_FILE_IG_COLLECTION_H
00003
00004 # ifdef PROJECT_NAME
00005 # include <Iguana/Framework/interface/IgLinearAlgebra.h>
00006 # else
00007 # include <IgLinearAlgebra.h>
00008 # endif
00009 #include <cstring>
00010 #include <string>
00011 #include <cassert>
00012 #include <vector>
00013 #include <map>
00014 #include <iostream>
00015 #include <algorithm>
00016
00017 enum AssociatedType
00018 {
00019 LEFT_ASSOCIATED = 1,
00020 RIGHT_ASSOCIATED = 2,
00021 BOTH_ASSOCIATED = 3
00022 };
00023
00024 class IgRef
00025 {
00026 public:
00027 IgRef()
00028 {}
00029
00030 IgRef(int collectionId, int objectId)
00031 : m_collectionId(collectionId), m_objectId(objectId)
00032 {}
00033
00034 IgRef(const IgRef &ref)
00035 : m_collectionId(ref.collectionId()),
00036 m_objectId(ref.objectId())
00037 {}
00038
00039 int collectionId(void) const
00040 {return m_collectionId;}
00041
00042 int objectId(void) const
00043 {return m_objectId;}
00044
00045 void set (int collectionId, int objectId)
00046 {
00047 m_collectionId = collectionId;
00048 m_objectId = objectId;
00049 }
00050 private:
00051 int m_collectionId;
00052 int m_objectId;
00053 };
00054
00055 class IgAssociation
00056 {
00057 public:
00058 IgAssociation(const IgRef &a, const IgRef &b)
00059 :m_refA(a), m_refB(b)
00060 {}
00061
00062 IgAssociation()
00063 {}
00064
00065 const IgRef &first(void) const
00066 {return m_refA; };
00067
00068 const IgRef &second(void) const
00069 {return m_refB; };
00070
00071 void set (int cA, int oA, int cB, int oB)
00072 {
00073 m_refA.set(cA, oA);
00074 m_refB.set(cB, oB);
00075 }
00076 private:
00077 IgRef m_refA;
00078 IgRef m_refB;
00079 };
00080
00081 enum ColumnType {
00082 INT_COLUMN = 0,
00083 STRING_COLUMN,
00084 DOUBLE_COLUMN,
00085 VECTOR_2D,
00086 VECTOR_3D,
00087 VECTOR_4D,
00088 NUMBER_OF_BASE_TYPES
00089 };
00090
00091
00092 template <class T>
00093 struct ColumnTypeHelper
00094 {
00095 static ColumnType typeId (void)
00096 {
00097 assert(false);
00098 return -1;
00099 }
00100 };
00101
00102 template <>
00103 struct ColumnTypeHelper<int>
00104 {
00105 static ColumnType typeId(void)
00106 {
00107 return INT_COLUMN;
00108 }
00109 };
00110
00111 template <>
00112 struct ColumnTypeHelper<double>
00113 {
00114 static ColumnType typeId(void)
00115 {
00116 return DOUBLE_COLUMN;
00117 }
00118 };
00119
00120 template <>
00121 struct ColumnTypeHelper<std::string>
00122 {
00123 static ColumnType typeId(void)
00124 {
00125 return STRING_COLUMN;
00126 }
00127 };
00128
00129 template <>
00130 struct ColumnTypeHelper<IgV2d>
00131 {
00132 static ColumnType typeId(void)
00133 { return VECTOR_2D; }
00134 };
00135
00136 template <>
00137 struct ColumnTypeHelper<IgV3d>
00138 {
00139 static ColumnType typeId(void)
00140 { return VECTOR_3D; }
00141 };
00142
00143 template <>
00144 struct ColumnTypeHelper<IgV4d>
00145 {
00146 static ColumnType typeId(void)
00147 { return VECTOR_4D; }
00148 };
00149
00150 class IgColumnHandle
00151 {
00152 public:
00153 IgColumnHandle (void *data, ColumnType type)
00154 :m_data(data), m_type(type)
00155 { }
00156
00157 ColumnType type(void)
00158 { return m_type; }
00159
00160 void *data(void) const
00161 { return m_data; }
00162
00163 template <class T>
00164 T &get (int index)
00165 {
00166 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00167 return data[index];
00168 }
00169
00170 int size(void)
00171 {
00172 switch (type())
00173 {
00174 case INT_COLUMN:
00175 return static_cast<std::vector<int> *>(m_data)->size();
00176 break;
00177 case STRING_COLUMN:
00178 return static_cast<std::vector<std::string> *>(m_data)->size();
00179 break;
00180 case DOUBLE_COLUMN:
00181 return static_cast<std::vector<double> *>(m_data)->size();
00182 break;
00183 case VECTOR_2D:
00184 return static_cast<std::vector<IgV2d> *>(m_data)->size();
00185 break;
00186 case VECTOR_3D:
00187 return static_cast<std::vector<IgV3d> *>(m_data)->size();
00188 break;
00189 case VECTOR_4D:
00190 return static_cast<std::vector<IgV4d> *>(m_data)->size();
00191 break;
00192 default:
00193 assert (false);
00194 }
00195 }
00196
00197 void stream(std::ostream &stream, int position)
00198 {
00199 switch (type())
00200 {
00201 case INT_COLUMN:
00202 stream << get<int>(position);
00203 break;
00204 case STRING_COLUMN:
00205 stream << "\""<< get<std::string>(position) << "\"";
00206 break;
00207 case DOUBLE_COLUMN:
00208 stream << get<double>(position);
00209 break;
00210 case VECTOR_2D:
00211 {
00212 IgV2d &v = get<IgV2d>(position);
00213 stream << "("<< v.x() << ", " << v.y() << ")";
00214 }
00215 break;
00216 case VECTOR_3D:
00217 {
00218 IgV3d &v = get<IgV3d>(position);
00219 stream << "("<< v.x() << ", " << v.y() << ", " << v.z() << ")";
00220 }
00221 break;
00222 case VECTOR_4D:
00223 {
00224 IgV4d &v = get<IgV4d>(position);
00225 stream << "("<< v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << ")";
00226 }
00227 break;
00228 default:
00229 assert (false);
00230 }
00231 }
00232
00233 void streamType (std::ostream &stream)
00234 {
00235 switch (type())
00236 {
00237 case INT_COLUMN:
00238 stream << "int";
00239 break;
00240 case STRING_COLUMN:
00241 stream << "string";
00242 break;
00243 case DOUBLE_COLUMN:
00244 stream << "double";
00245 break;
00246 case VECTOR_2D:
00247 stream << "v2d";
00248 break;
00249 case VECTOR_3D:
00250 stream << "v3d";
00251 break;
00252 case VECTOR_4D:
00253 stream << "v4d";
00254 break;
00255 default:
00256 assert (false);
00257 }
00258 }
00259
00260 void extend ()
00261 {
00262 switch (m_type)
00263 {
00264 case INT_COLUMN:
00265 return doExtend<int>();
00266 break;
00267 case DOUBLE_COLUMN:
00268 return doExtend<double>();
00269 break;
00270 case STRING_COLUMN:
00271 return doExtend<std::string>();
00272 break;
00273 case VECTOR_2D:
00274 return doExtend<IgV2d>();
00275 break;
00276 case VECTOR_3D:
00277 return doExtend<IgV3d>();
00278 break;
00279 case VECTOR_4D:
00280 return doExtend<IgV4d>();
00281 break;
00282 default:
00283 assert(false);
00284 break;
00285 }
00286 }
00287
00288 void resize (unsigned int newSize)
00289 {
00290 switch (m_type)
00291 {
00292 case INT_COLUMN:
00293 return doResize<int>(newSize);
00294 break;
00295 case DOUBLE_COLUMN:
00296 return doResize<double>(newSize);
00297 break;
00298 case STRING_COLUMN:
00299 return doResize<std::string>(newSize);
00300 break;
00301 case VECTOR_2D:
00302 return doResize<IgV2d>(newSize);
00303 break;
00304 case VECTOR_3D:
00305 return doResize<IgV3d>(newSize);
00306 break;
00307 case VECTOR_4D:
00308 return doResize<IgV4d>(newSize);
00309 break;
00310 default:
00311 assert(false);
00312 break;
00313 }
00314 }
00315
00316 void reserve(unsigned int size)
00317 {
00318 switch (m_type)
00319 {
00320 case INT_COLUMN:
00321 doReserve<int>(size);
00322 break;
00323 case DOUBLE_COLUMN:
00324 doReserve<double>(size);
00325 break;
00326 case STRING_COLUMN:
00327 doReserve<std::string>(size);
00328 break;
00329 case VECTOR_2D:
00330 doReserve<IgV2d>(size);
00331 break;
00332 case VECTOR_3D:
00333 doReserve<IgV3d>(size);
00334 break;
00335 case VECTOR_4D:
00336 doReserve<IgV4d>(size);
00337 break;
00338 default:
00339 assert(false);
00340 break;
00341 }
00342 }
00343
00344 void compress()
00345 {
00346 switch (m_type)
00347 {
00348 case INT_COLUMN:
00349 doCompress<int>();
00350 break;
00351 case DOUBLE_COLUMN:
00352 doCompress<double>();
00353 break;
00354 case STRING_COLUMN:
00355 doCompress<std::string>();
00356 break;
00357 case VECTOR_2D:
00358 doCompress<IgV2d>();
00359 break;
00360 case VECTOR_3D:
00361 doCompress<IgV3d>();
00362 break;
00363 case VECTOR_4D:
00364 doCompress<IgV4d>();
00365 break;
00366 default:
00367 assert(false);
00368 break;
00369 }
00370 }
00371
00372 void clear()
00373 {
00374 switch (m_type)
00375 {
00376 case INT_COLUMN:
00377 doClear<int>();
00378 break;
00379 case DOUBLE_COLUMN:
00380 doClear<double>();
00381 break;
00382 case STRING_COLUMN:
00383 doClear<std::string>();
00384 break;
00385 case VECTOR_2D:
00386 doClear<IgV2d>();
00387 break;
00388 case VECTOR_3D:
00389 doClear<IgV3d>();
00390 break;
00391 case VECTOR_4D:
00392 doClear<IgV4d>();
00393 break;
00394 default:
00395 assert(false);
00396 break;
00397 }
00398 }
00399
00400 template <class T>
00401 void doExtend()
00402 {
00403 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00404 data.resize(data.size()+1);
00405 }
00406
00407 template <class T>
00408 void doReserve(unsigned int size)
00409 {
00410 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00411 data.reserve(size);
00412 }
00413
00414 template <class T>
00415 void doCompress(void)
00416 {
00417 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00418 data.reserve(data.size());
00419 }
00420
00421 template <class T>
00422 void doClear(void)
00423 {
00424 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00425 data.clear();
00426 }
00427
00428 template <class T>
00429 void doResize(int newSize)
00430 {
00431 std::vector<T> &data = *(static_cast<std::vector<T> *>(m_data));
00432 data.resize(newSize);
00433 }
00434
00435 void destroy()
00436 {
00437 switch (m_type)
00438 {
00439 case INT_COLUMN:
00440 doDestroy<int>();
00441 break;
00442 case DOUBLE_COLUMN:
00443 doDestroy<double>();
00444 break;
00445 case STRING_COLUMN:
00446 doDestroy<std::string>();
00447 break;
00448 case VECTOR_2D:
00449 doDestroy<IgV2d>();
00450 break;
00451 case VECTOR_3D:
00452 doDestroy<IgV3d>();
00453 break;
00454 case VECTOR_4D:
00455 doDestroy<IgV4d>();
00456 break;
00457 default:
00458 assert(false);
00459 break;
00460 }
00461 }
00462
00463
00464 private:
00465 template <class T>
00466 void doDestroy(void)
00467 {
00468 std::vector<T> *data = static_cast<std::vector<T> *>(m_data);
00469 data->clear();
00470 delete data;
00471 }
00472
00473
00474 void *m_data;
00475 ColumnType m_type;
00476 };
00477
00478 class IgProperty
00479 {
00480 public:
00481 IgProperty(IgColumnHandle &handle)
00482 : m_handle(handle)
00483 { }
00484
00485 IgColumnHandle &handle(void)
00486 { return m_handle; }
00487
00488 private:
00489 IgColumnHandle m_handle;
00490 };
00491
00492 class IgCollectionItem;
00493 class IgCollection;
00494
00495 class IgCollectionIterator
00496 {
00497 public:
00498 IgCollectionIterator(IgCollection *collection, int rowPosition)
00499 :m_collection(collection), m_rowPosition(rowPosition)
00500 { }
00501
00502 IgCollectionItem operator*();
00503
00504 void operator++(int )
00505 {
00506 m_rowPosition++;
00507 }
00508
00509 void operator--(int )
00510 {
00511 m_rowPosition--;
00512 }
00513
00514 void operator+=(int delta)
00515 {
00516 m_rowPosition += delta;
00517 }
00518
00519 void operator-=(int delta)
00520 {
00521 m_rowPosition -= delta;
00522 }
00523
00524 void operator=(int value)
00525 {
00526 m_rowPosition = value;
00527 }
00528
00529 bool operator==(const IgCollectionIterator& other)
00530 {
00531 return m_rowPosition == other.m_rowPosition;
00532 }
00533
00534 bool operator!=(const IgCollectionIterator& other)
00535 {
00536 return m_rowPosition != other.m_rowPosition;
00537 }
00538
00539 IgCollectionIterator operator+(int value)
00540 {
00541 return IgCollectionIterator(m_collection, m_rowPosition + value);
00542 }
00543
00544 private:
00545 IgCollection *m_collection;
00546 int m_rowPosition;
00547 };
00548
00552 struct IgSchemaError
00553 {
00554 };
00555
00556
00557
00558
00559
00560 class IgCollection
00561 {
00562 public:
00563 typedef std::vector<std::string> Labels;
00564 typedef std::pair<const char *, IgColumnHandle> LabelColumn;
00565 typedef std::pair<ColumnType, IgColumnHandle> TypeColumn;
00566 typedef std::vector<IgProperty> Properties;
00567
00568 template <class T>
00569 IgProperty &addProperty(const char *label, T defaultValue)
00570 {
00571 Labels::iterator l;
00572 if (doHasProperty(label, &l))
00573 {
00574 return m_properties[std::distance(m_labels.begin(), l)];
00575 }
00576
00577 m_labels.push_back(label);
00578 std::vector<T> *columnData = new std::vector<T>;
00579 IgColumnHandle handle((void *)columnData, ColumnTypeHelper<T>::typeId ());
00580 m_columnLabelsIndex.push_back(LabelColumn(m_labels.back().c_str(), handle));
00581 m_columnTypesIndex[ColumnTypeHelper<T>::typeId()].push_back(handle);
00582 m_properties.push_back (IgProperty(handle));
00583 return m_properties.back();
00584 }
00585
00586 IgCollectionIterator begin(void);
00587 IgCollectionIterator end(void);
00588
00589 IgProperty &getProperty (const char *label)
00590 {
00591 Labels::iterator l;
00592 if (!doHasProperty (label, &l))
00593 {
00594 throw IgSchemaError();
00595 }
00596
00597 return m_properties[std::distance(m_labels.begin(), l)];
00598 }
00599
00600 bool hasProperty (const char *label)
00601 {
00602 return doHasProperty(label);
00603 }
00604
00605 int size(void)
00606 {
00607
00608
00609 return m_rowCount;
00610 }
00611
00612 IgColumnHandle &getHandleByLabel(const char *label)
00613 {
00614 for (std::vector<LabelColumn>::iterator i = m_columnLabelsIndex.begin();
00615 i != m_columnLabelsIndex.end();
00616 i++)
00617 {
00618 if (strcmp(i->first, label) == 0)
00619 {
00620 return i->second;
00621 }
00622 }
00623 std::cout << "IgColumnHandle::getHandleByLabel " << label << " from " << m_name << std::endl;
00624
00625 assert(false && "Column not found. Did you create it?");
00626 }
00627
00628 IgColumnHandle &getHandleByPosition(const unsigned int position)
00629 {
00630 return m_properties[position].handle();
00631 }
00632
00633 void reserve(unsigned int size)
00634 {
00635 for (Properties::iterator i = m_properties.begin();
00636 i != m_properties.end();
00637 i++)
00638 {
00639 i->handle().reserve(size);
00640 }
00641 }
00642
00643 void resize(unsigned int size)
00644 {
00645 for (Properties::iterator i = m_properties.begin();
00646 i != m_properties.end();
00647 i++)
00648 {
00649 i->handle().resize(size);
00650 }
00651 m_rowCount = size;
00652 }
00653
00654 void compress(void)
00655 {
00656 for (Properties::iterator i = m_properties.begin();
00657 i != m_properties.end();
00658 i++)
00659 {
00660 i->handle().compress();
00661 }
00662 }
00663
00664 void clear(void)
00665 {
00666 for (Properties::iterator i = m_properties.begin ();
00667 i != m_properties.end();
00668 i++)
00669 {
00670 i->handle().clear();
00671 }
00672 }
00673
00674 Properties &properties(void)
00675 {
00676 return m_properties;
00677 }
00678
00679 IgCollectionItem create();
00680 const char *name(void) const
00681 {
00682 return m_name.c_str();
00683 }
00684
00685 int id(void) const
00686 {
00687 return m_id;
00688 }
00689
00690 std::vector<LabelColumn> &columnLabels(void)
00691 { return m_columnLabelsIndex; };
00692
00693 protected:
00694 IgCollection (const char *name, int id)
00695 : m_name (name), m_id(id), m_rowCount(0)
00696 { }
00697
00698 ~IgCollection ()
00699 {
00700 }
00701
00702 friend class IgDataStorage;
00703
00704 private:
00705 bool doHasProperty (const char *label, Labels::iterator *i = 0)
00706 {
00707 Labels::iterator l = std::find(m_labels.begin(), m_labels.end(), label);
00708 if (i != 0)
00709 *i = l;
00710 return l != m_labels.end();
00711 }
00712
00713 typedef std::vector<LabelColumn> ColumnLabels;
00714 typedef std::vector<TypeColumn> ColumnTypes;
00715 typedef std::map<ColumnType, std::vector<IgColumnHandle> > ColumnTypeIndex;
00716 std::vector<std::string> m_labels;
00717 std::vector<int> m_primaryKeys;
00718 std::vector<LabelColumn> m_columnLabelsIndex;
00719 Properties m_properties;
00720 ColumnTypeIndex m_columnTypesIndex;
00721 std::string m_name;
00722 int m_id;
00723 int m_rowCount;
00724 };
00725
00726
00727 template <class T>
00728 struct IgStorageGetterTrait
00729 { typedef T storage_type; };
00730
00731 template <>
00732 struct IgStorageGetterTrait<char *>
00733 { typedef std::string storage_type; };
00734
00735 template <>
00736 struct IgStorageGetterTrait<const char *>
00737 { typedef std::string storage_type; };
00738
00739 class IgCollectionItem
00740 {
00741 public:
00742 IgCollectionItem (IgCollection *collection, int position)
00743 :m_collection(collection), m_position(position), m_propertyPosition(0)
00744 {
00745 }
00746
00747 int currentColumn()
00748 {
00749 return m_propertyPosition;
00750 }
00751
00752 int currentRow()
00753 {
00754 return m_position;
00755 }
00756
00757 IgCollectionItem &nextColumn(void)
00758 {
00759 m_propertyPosition++;
00760 return *this;
00761 }
00762
00763 IgCollectionItem &moveToColumn(const IgColumnHandle &handle)
00764 {
00765 void *data = handle.data();
00766 int j = 0;
00767 for (IgCollection::Properties::iterator i = m_collection->properties().begin();
00768 (i != m_collection->properties().end()) && (i->handle().data() != data);
00769 i++)
00770 { j++; }
00771 m_propertyPosition = j;
00772 return *this;
00773 }
00774
00775 IgCollectionItem &operator*(void)
00776 {
00777 return *this;
00778 }
00779
00780 template <class T>
00781 T ¤t(void)
00782 {
00783 return currentHandle().get<T>(m_position);
00784 }
00785
00786 IgCollectionItem &operator[](IgProperty &property)
00787 {
00788 return this->moveToColumn(property.handle());
00789 }
00790
00791 IgCollectionItem &operator[](const char *label)
00792 {
00793 assert(m_collection && "Collection ptr is 0");
00794 return this->moveToColumn(m_collection->getHandleByLabel(label));
00795 }
00796
00797 template <class T>
00798 IgCollectionItem &operator=(T value)
00799 {
00800 currentHandle().get<typename IgStorageGetterTrait<T>::storage_type>(m_position) = value;
00801 return *this;
00802 }
00803
00804 IgCollectionItem &operator=(const std::string &value)
00805 {
00806 currentHandle().get<std::string>(m_position) = value;
00807 return *this;
00808 }
00809
00810 IgCollectionItem &operator=(const char *value)
00811 {
00812 currentHandle().get<std::string>(m_position) = value;
00813 return *this;
00814 }
00815
00816 template <class T, class A, template <typename, typename> class C>
00817 IgCollectionItem &operator=(C<T,A> container)
00818 {
00819 ContainerTraits<C,T,A>::put(m_collection,
00820 m_propertyPosition,
00821 m_position,
00822 container);
00823 return *this;
00824 }
00825
00826 template <class T>
00827 IgCollectionItem &operator,(T value)
00828 {
00829 m_propertyPosition++;
00830 currentHandle().get<T>(m_position) = value;
00831 return *this;
00832 }
00833
00834 IgCollectionItem &operator,(const char *value)
00835 {
00836 m_propertyPosition++;
00837 currentHandle().get<std::string>(m_position) = value;
00838 return *this;
00839 }
00840
00841 IgCollectionItem &operator,(const std::string &value)
00842 {
00843 m_propertyPosition++;
00844 currentHandle().get<std::string>(m_position) = value;
00845 return *this;
00846 }
00847
00848
00849 template <class T, class A, template <typename, typename> class C>
00850 IgCollectionItem &operator,(C<T, A> container)
00851 {
00852 m_propertyPosition=ContainerTraits<C,T,A>::put(m_collection,
00853 m_propertyPosition,
00854 m_position,
00855 container);
00856 return *this;
00857 }
00858
00859 template <class T>
00860 T &get(const char *label)
00861 {
00862 return m_collection->getHandleByLabel(label).get<T>(m_position);
00863 }
00864
00865 template <class T>
00866 T &get(IgProperty &property)
00867 {
00868 return property.handle().get<T>(m_position);
00869 }
00870
00871 template <class T>
00872 void set(IgProperty &property, T value)
00873 {
00874 property.handle().get<T>(m_position) = value;
00875 }
00876
00877 template <class T>
00878 void set(const char *label, T value)
00879 {
00880 this->get<T>(label) = value;
00881 }
00882
00883 void stream(std::ostream &stream)
00884 {
00885 for (IgCollection::Properties::iterator i = m_collection->properties().begin();
00886 i != m_collection->properties().end();
00887 i++)
00888 {
00889 IgColumnHandle &handle = i->handle();
00890 handle.stream(stream, m_position);
00891 if (i+1 != m_collection->properties().end())
00892 {
00893 stream << ", ";
00894 }
00895 }
00896 }
00897
00898 operator IgRef() const
00899 { return IgRef(m_collection->id(), m_position); }
00900
00901 private:
00902 template <template <typename, typename> class C, class T, class A>
00903 struct ContainerTraits
00904 {
00905 static unsigned int put (IgCollection *collection,
00906 unsigned int propertyPosition,
00907 unsigned int position, C<T,A> container)
00908 {
00909 for (typename C<T,A>::iterator i = container.begin();
00910 i != container.end();
00911 i++)
00912 {
00913 collection->getHandleByPosition(propertyPosition)
00914 .get<T>(position) = *i;
00915 propertyPosition++;
00916 }
00917 return propertyPosition;
00918 }
00919 };
00920
00921 IgColumnHandle ¤tHandle()
00922 {
00923 return m_collection->getHandleByPosition(m_propertyPosition);
00924 }
00925
00926 IgCollection *m_collection;
00927 unsigned int m_position;
00928 unsigned int m_propertyPosition;
00929 };
00930
00931 class IgAssociationSet
00932 {
00933 public:
00934 typedef std::vector<IgAssociation> Associations;
00935 typedef Associations::iterator Iterator;
00936
00937 IgAssociationSet(const char *name)
00938 :m_name(name)
00939 { }
00940
00941 void associate (const IgRef &a, const IgRef &b)
00942 { m_associations.push_back(IgAssociation(a, b)); }
00943
00944 const char *name(void)
00945 {return m_name.c_str(); }
00946
00947 Iterator begin(void)
00948 { return m_associations.begin(); }
00949
00950 Iterator end(void)
00951 { return m_associations.end(); }
00952
00953 int size(void)
00954 { return m_associations.size(); }
00955
00956 void clear(void)
00957 { m_associations.clear(); }
00958
00959 void reserve(unsigned int capacity)
00960 { m_associations.reserve(capacity);}
00961
00962 void resize(unsigned int newSize)
00963 { m_associations.resize(newSize);}
00964
00965 void compress(void)
00966 { m_associations.reserve(m_associations.size());}
00967
00968 IgAssociation &operator[](unsigned int pos)
00969 {
00970 return m_associations[pos];
00971 }
00972 private:
00973 std::string m_name;
00974 Associations m_associations;
00975 };
00976
00977 class IgAssociatedSet;
00978
00979 class IgDataStorage
00980 {
00981 public:
00982
00983 typedef std::vector<std::string> CollectionNames;
00984 typedef std::vector<std::string> AssociationSetNames;
00985 typedef std::vector<IgCollection *> Collections;
00986 typedef std::vector<IgAssociationSet *> AssociationSets;
00987
00988
00989
00990 ~IgDataStorage (void)
00991 {
00992 for (AssociationSets::iterator i = m_associationSets.begin();
00993 i != m_associationSets.end();
00994 i++)
00995 {
00996 delete *i;
00997 }
00998
00999 for (Collections::iterator i = m_collections.begin();
01000 i != m_collections.end();
01001 i++)
01002 {
01003 for (IgCollection::Properties::iterator j = (*i)->properties().begin();
01004 j != (*i)->properties().end();
01005 j++)
01006 {
01007 j->handle().destroy();
01008 }
01009 delete *i;
01010 }
01011 }
01012
01013
01014
01015
01016
01017 IgCollection &getCollection(const char *label)
01018 {
01019 return *getCollectionPtr(label);
01020 }
01021
01022 IgAssociatedSet getAssociatedSetPtr(IgAssociationSet *associations,
01023 IgCollectionItem &item,
01024 AssociatedType which = BOTH_ASSOCIATED);
01025
01026 IgAssociatedSet getAssociatedSet(const char *name,
01027 IgCollectionItem &item,
01028 AssociatedType which = BOTH_ASSOCIATED);
01029
01030 IgCollection &getCollectionByIndex(unsigned int index)
01031 {
01032 assert(index >= 0);
01033 assert(index < m_collections.size());
01034 return *(m_collections[index]);
01035 }
01036
01037 IgCollection *getCollectionPtr(const char *label)
01038 {
01039 CollectionNames::iterator n = std::find (m_collectionNames.begin(),
01040 m_collectionNames.end(),
01041 label);
01042
01043 if (n == m_collectionNames.end())
01044 {
01045 IgCollection *collection = new IgCollection(label, m_collections.size ());
01046 m_collectionNames.push_back(label);
01047 m_collections.push_back(collection);
01048 return collection;
01049 }
01050 return m_collections[std::distance(m_collectionNames.begin(), n)];
01051 }
01052
01053 IgAssociationSet &getAssociationSet(const char *label)
01054 {
01055 return *getAssociationSetPtr(label);
01056 }
01057
01058 IgAssociationSet *getAssociationSetPtr(const char * label)
01059 {
01060 AssociationSetNames::iterator n = std::find(m_associationSetNames.begin(),
01061 m_associationSetNames.end(),
01062 label);
01063 if (n == m_associationSetNames.end())
01064 {
01065 IgAssociationSet *associationSet = new IgAssociationSet(label);
01066 m_associationSetNames.push_back(label);
01067 m_associationSets.push_back(associationSet);
01068 return associationSet;
01069 }
01070 return m_associationSets[std::distance(m_associationSetNames.begin(), n)];
01071 }
01072
01073 IgCollectionItem deref(const IgRef &ref)
01074 {
01075 return IgCollectionItem(m_collections[ref.collectionId()],
01076 ref.objectId());
01077 }
01078
01079 CollectionNames &collectionNames(void)
01080 {
01081 return m_collectionNames;
01082 }
01083
01084 AssociationSetNames &associationSetNames(void)
01085 {
01086 return m_associationSetNames;
01087 }
01088
01089 bool empty(void)
01090 {
01091 return m_collectionNames.empty();
01092 }
01093
01094 bool hasCollection(const char *name)
01095 {
01096 return std::find (m_collectionNames.begin(), m_collectionNames.end(), name) != m_collectionNames.end();
01097 }
01098 private:
01099 CollectionNames m_collectionNames;
01100 AssociationSetNames m_associationSetNames;
01101 Collections m_collections;
01102 AssociationSets m_associationSets;
01103 };
01104
01105 class IgAssociatedSet
01106 {
01107 public:
01108 class Iterator
01109 {
01110 public:
01111
01112 Iterator(IgDataStorage *storage, IgAssociationSet::Iterator current,
01113 IgAssociationSet::Iterator end,
01114 const IgRef &item,
01115 enum AssociatedType associatedType = BOTH_ASSOCIATED)
01116 :m_storage(storage),
01117 m_cur(current),
01118 m_end(end),
01119 m_ref(item),
01120 m_associatedType(associatedType)
01121 {
01122 find();
01123 }
01124
01125 void operator++(int )
01126 {
01127 m_cur++;
01128 find();
01129 }
01130
01131 void find(void)
01132 {
01133 while(m_cur != m_end)
01134 {
01135 if ((m_associatedType & RIGHT_ASSOCIATED)
01136 && m_cur->first().objectId() == m_ref.objectId()
01137 && m_cur->first().collectionId() == m_ref.collectionId())
01138 {
01139 m_pos = 0;
01140 return;
01141 }
01142 if ((m_associatedType & LEFT_ASSOCIATED)
01143 && m_cur->second().objectId() == m_ref.objectId()
01144 && m_cur->second().collectionId() == m_ref.collectionId())
01145 {
01146 m_pos = 1;
01147 return;
01148 }
01149 m_cur++;
01150 }
01151 }
01152
01153 bool operator==(const Iterator &other)
01154 {
01155 return other.m_cur == this->m_cur;
01156 }
01157
01158 bool operator!=(const Iterator &other)
01159 {
01160 return other.m_cur != this->m_cur;
01161 }
01162
01163 IgCollectionItem operator*(void)
01164 {
01165 return m_storage->deref(m_pos ? m_cur->first() : m_cur->second());
01166 }
01167
01168 private:
01169 IgDataStorage *m_storage;
01170 IgAssociationSet::Iterator m_cur;
01171 IgAssociationSet::Iterator m_end;
01172 const IgRef m_ref;
01173 int m_pos;
01174 enum AssociatedType m_associatedType;
01175 };
01176
01177 IgAssociatedSet(IgDataStorage *storage,
01178 IgAssociationSet *associations,
01179 IgCollectionItem *item,
01180 enum AssociatedType associatedType = BOTH_ASSOCIATED)
01181 : m_storage(storage),
01182 m_associations(associations),
01183 m_item(item),
01184 m_associatedType(associatedType)
01185 { }
01186
01187 Iterator begin(void)
01188 {
01189 Iterator result(m_storage,
01190 m_associations->begin(),
01191 m_associations->end(),
01192 static_cast<IgRef>(*m_item), m_associatedType);
01193 return result;
01194 }
01195
01196 Iterator end(void)
01197 { return Iterator(m_storage, m_associations->end(),
01198 m_associations->end(),
01199 static_cast<const IgRef>(*m_item), m_associatedType); }
01200 private:
01201 IgDataStorage *m_storage;
01202 IgAssociationSet *m_associations;
01203 IgCollectionItem *m_item;
01204 enum AssociatedType m_associatedType;
01205 };
01206
01207
01208 std::ostream &operator<<(std::ostream &stream, IgCollection &collection);
01209 std::ostream &operator<<(std::ostream &stream, const IgRef &ref);
01210 std::ostream &operator<<(std::ostream &stream, const IgAssociation &association);
01211 std::ostream &operator<<(std::ostream &stream, IgAssociationSet &associationSet);
01212 std::ostream &operator<<(std::ostream &stream, IgDataStorage &storage);
01213
01214 #endif