/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ #ifndef _DECAF_UTIL_STLMAP_H_ #define _DECAF_UTIL_STLMAP_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace decaf{ namespace util{ /** * Map template that wraps around a std::map to provide * a more user-friendly interface and to provide common * functions that do not exist in std::map. * * @since 1.0 */ template > class StlMap : public Map { private: std::map valueMap; mutable concurrent::Mutex mutex; int modCount; private: class AbstractMapIterator { protected: mutable int position; int expectedModCount; typename std::map::iterator futureEntry; typename std::map::iterator currentEntry; StlMap* associatedMap; private: AbstractMapIterator(const AbstractMapIterator&); AbstractMapIterator& operator= (const AbstractMapIterator&); public: AbstractMapIterator(StlMap* parent) : position(0), expectedModCount(parent->modCount), futureEntry(parent->valueMap.begin()), currentEntry(parent->valueMap.end()), associatedMap(parent) { } virtual ~AbstractMapIterator() {} virtual bool checkHasNext() const { if (futureEntry != this->associatedMap->valueMap.end()) { return true; } return false; } void checkConcurrentMod() const { if (expectedModCount != this->associatedMap->modCount) { throw ConcurrentModificationException( __FILE__, __LINE__, "StlMap modified outside this iterator"); } } void makeNext() { checkConcurrentMod(); if (!checkHasNext()) { throw NoSuchElementException(__FILE__, __LINE__, "No next element"); } currentEntry = futureEntry; futureEntry++; } virtual void doRemove() { checkConcurrentMod(); if (currentEntry == this->associatedMap->valueMap.end()) { throw decaf::lang::exceptions::IllegalStateException( __FILE__, __LINE__, "Remove called before call to next()"); } this->associatedMap->valueMap.erase(currentEntry); currentEntry = this->associatedMap->valueMap.end(); expectedModCount++; associatedMap->modCount++; } }; class EntryIterator : public Iterator< MapEntry >, public AbstractMapIterator { private: EntryIterator(const EntryIterator&); EntryIterator& operator= (const EntryIterator&); public: EntryIterator(StlMap* parent) : AbstractMapIterator(parent) { } virtual ~EntryIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual MapEntry next() { this->makeNext(); return MapEntry(this->currentEntry->first, this->currentEntry->second); } virtual void remove() { this->doRemove(); } }; class KeyIterator : public Iterator, public AbstractMapIterator { private: KeyIterator(const KeyIterator&); KeyIterator& operator= (const KeyIterator&); public: KeyIterator(StlMap* parent) : AbstractMapIterator(parent) { } virtual ~KeyIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual K next() { this->makeNext(); return this->currentEntry->first; } virtual void remove() { this->doRemove(); } }; class ValueIterator : public Iterator, public AbstractMapIterator { private: ValueIterator(const ValueIterator&); ValueIterator& operator= (const ValueIterator&); public: ValueIterator(StlMap* parent) : AbstractMapIterator(parent) { } virtual ~ValueIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual V next() { this->makeNext(); return this->currentEntry->second; } virtual void remove() { this->doRemove(); } }; private: class ConstAbstractMapIterator { protected: mutable int position; int expectedModCount; typename std::map::const_iterator futureEntry; typename std::map::const_iterator currentEntry; const StlMap* associatedMap; private: ConstAbstractMapIterator(const ConstAbstractMapIterator&); ConstAbstractMapIterator& operator= (const ConstAbstractMapIterator&); public: ConstAbstractMapIterator(const StlMap* parent) : position(0), expectedModCount(parent->modCount), futureEntry(parent->valueMap.begin()), currentEntry(parent->valueMap.end()), associatedMap(parent) { } virtual ~ConstAbstractMapIterator() {} virtual bool checkHasNext() const { if (futureEntry != this->associatedMap->valueMap.end()) { return true; } return false; } void checkConcurrentMod() const { if (expectedModCount != this->associatedMap->modCount) { throw ConcurrentModificationException( __FILE__, __LINE__, "StlMap modified outside this iterator"); } } void makeNext() { checkConcurrentMod(); if (!checkHasNext()) { throw NoSuchElementException(__FILE__, __LINE__, "No next element"); } currentEntry = futureEntry; futureEntry++; } }; class ConstEntryIterator : public Iterator< MapEntry >, public ConstAbstractMapIterator { private: ConstEntryIterator(const ConstEntryIterator&); ConstEntryIterator& operator= (const ConstEntryIterator&); public: ConstEntryIterator(const StlMap* parent) : ConstAbstractMapIterator(parent) { } virtual ~ConstEntryIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual MapEntry next() { this->makeNext(); return MapEntry(this->currentEntry->first, this->currentEntry->second); } virtual void remove() { throw lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Cannot write to a const Iterator." ); } }; class ConstKeyIterator : public Iterator, public ConstAbstractMapIterator { private: ConstKeyIterator(const ConstKeyIterator&); ConstKeyIterator& operator= (const ConstKeyIterator&); public: ConstKeyIterator(const StlMap* parent) : ConstAbstractMapIterator(parent) { } virtual ~ConstKeyIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual K next() { this->makeNext(); return this->currentEntry->first; } virtual void remove() { throw lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Cannot write to a const Iterator." ); } }; class ConstValueIterator : public Iterator, public ConstAbstractMapIterator { private: ConstValueIterator(const ConstValueIterator&); ConstValueIterator& operator= (const ConstValueIterator&); public: ConstValueIterator(const StlMap* parent) : ConstAbstractMapIterator(parent) { } virtual ~ConstValueIterator() {} virtual bool hasNext() const { return this->checkHasNext(); } virtual V next() { this->makeNext(); return this->currentEntry->second; } virtual void remove() { throw lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Cannot write to a const Iterator." ); } }; private: // Special Set implementation that is backed by this HashMap class StlMapEntrySet : public AbstractSet< MapEntry > { private: StlMap* associatedMap; private: StlMapEntrySet(const StlMapEntrySet&); StlMapEntrySet& operator= (const StlMapEntrySet&); public: StlMapEntrySet(StlMap* parent) : AbstractSet< MapEntry >(), associatedMap(parent) { } virtual ~StlMapEntrySet() {} virtual int size() const { return associatedMap->size(); } virtual void clear() { associatedMap->clear(); } virtual bool remove(const MapEntry& entry) { if (this->associatedMap->containsKey(entry.getKey()) && this->associatedMap->get(entry.getKey()) == entry.getValue()) { associatedMap->remove(entry.getKey()); return true; } return false; } virtual bool contains(const MapEntry& entry) { if (this->associatedMap->containsKey(entry.getKey()) && this->associatedMap->get(entry.getKey()) == entry.getValue()) { return true; } return false; } virtual Iterator< MapEntry >* iterator() { return new EntryIterator(associatedMap); } virtual Iterator< MapEntry >* iterator() const { return new ConstEntryIterator(associatedMap); } }; // Special Set implementation that is backed by this HashMap class ConstStlMapEntrySet : public AbstractSet< MapEntry > { private: const StlMap* associatedMap; private: ConstStlMapEntrySet(const ConstStlMapEntrySet&); ConstStlMapEntrySet& operator= (const ConstStlMapEntrySet&); public: ConstStlMapEntrySet(const StlMap* parent) : AbstractSet< MapEntry >(), associatedMap(parent) { } virtual ~ConstStlMapEntrySet() {} virtual int size() const { return associatedMap->size(); } virtual void clear() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't clear a const collection"); } virtual bool remove(const MapEntry& entry DECAF_UNUSED) { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't remove from const collection"); } virtual bool contains(const MapEntry& entry) { if (this->associatedMap->containsKey(entry.getKey()) && this->associatedMap->get(entry.getKey()) == entry.getValue()) { return true; } return false; } virtual Iterator< MapEntry >* iterator() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); } virtual Iterator< MapEntry >* iterator() const { return new ConstEntryIterator(associatedMap); } }; private: class StlMapKeySet : public AbstractSet { private: StlMap* associatedMap; private: StlMapKeySet(const StlMapKeySet&); StlMapKeySet& operator= (const StlMapKeySet&); public: StlMapKeySet(StlMap* parent) : AbstractSet(), associatedMap(parent) { } virtual ~StlMapKeySet() {} virtual bool contains(const K& key) const { return this->associatedMap->containsKey(key); } virtual int size() const { return this->associatedMap->size(); } virtual void clear() { this->associatedMap->clear(); } virtual bool remove(const K& key) { if (this->associatedMap->containsKey(key)) { associatedMap->remove(key); return true; } return false; } virtual Iterator* iterator() { return new KeyIterator(this->associatedMap); } virtual Iterator* iterator() const { return new ConstKeyIterator(this->associatedMap); } }; class ConstStlMapKeySet : public AbstractSet { private: const StlMap* associatedMap; private: ConstStlMapKeySet(const ConstStlMapKeySet&); ConstStlMapKeySet& operator= (const ConstStlMapKeySet&); public: ConstStlMapKeySet(const StlMap* parent) : AbstractSet(), associatedMap(parent) { } virtual ~ConstStlMapKeySet() {} virtual bool contains(const K& key) const { return this->associatedMap->containsKey(key); } virtual int size() const { return this->associatedMap->size(); } virtual void clear() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't modify a const collection"); } virtual bool remove(const K& key DECAF_UNUSED) { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't modify a const collection"); } virtual Iterator* iterator() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); } virtual Iterator* iterator() const { return new ConstKeyIterator(this->associatedMap); } }; private: class StlMapValueCollection : public AbstractCollection { private: StlMap* associatedMap; private: StlMapValueCollection(const StlMapValueCollection&); StlMapValueCollection& operator= (const StlMapValueCollection&); public: StlMapValueCollection(StlMap* parent) : AbstractCollection(), associatedMap(parent) { } virtual ~StlMapValueCollection() {} virtual bool contains(const V& value) const { return this->associatedMap->containsValue(value); } virtual int size() const { return this->associatedMap->size(); } virtual void clear() { this->associatedMap->clear(); } virtual Iterator* iterator() { return new ValueIterator(this->associatedMap); } virtual Iterator* iterator() const { return new ConstValueIterator(this->associatedMap); } }; class ConstStlMapValueCollection : public AbstractCollection { private: const StlMap* associatedMap; private: ConstStlMapValueCollection(const ConstStlMapValueCollection&); ConstStlMapValueCollection& operator= (const ConstStlMapValueCollection&); public: ConstStlMapValueCollection(const StlMap* parent) : AbstractCollection(), associatedMap(parent) { } virtual ~ConstStlMapValueCollection() {} virtual bool contains(const V& value) const { return this->associatedMap->containsValue(value); } virtual int size() const { return this->associatedMap->size(); } virtual void clear() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't modify a const collection"); } virtual Iterator* iterator() { throw decaf::lang::exceptions::UnsupportedOperationException( __FILE__, __LINE__, "Can't return a non-const iterator for a const collection"); } virtual Iterator* iterator() const { return new ConstValueIterator(this->associatedMap); } }; private: // Cached values that are only initialized once a request for them is made. decaf::lang::Pointer cachedEntrySet; decaf::lang::Pointer cachedKeySet; decaf::lang::Pointer cachedValueCollection; // Cached values that are only initialized once a request for them is made. mutable decaf::lang::Pointer cachedConstEntrySet; mutable decaf::lang::Pointer cachedConstKeySet; mutable decaf::lang::Pointer cachedConstValueCollection; public: /** * Default constructor - does nothing. */ StlMap() : Map(), valueMap(), mutex(), modCount(0), cachedEntrySet(), cachedKeySet(), cachedValueCollection(), cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { } /** * Copy constructor - copies the content of the given map into this one. * * @param source * The source StlMap whose entries are copied into this Map. */ StlMap(const StlMap& source ) : Map(), valueMap(), mutex(), modCount(0), cachedEntrySet(), cachedKeySet(), cachedValueCollection(), cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { copy(source); } /** * Copy constructor - copies the content of the given map into this one. * * @param source * The source ma whose entries are copied into this Map.. */ StlMap(const Map& source) : Map(), valueMap(), mutex(), modCount(0), cachedEntrySet(), cachedKeySet(), cachedValueCollection(), cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() { copy(source); } virtual ~StlMap() {} /** * {@inheritDoc} */ virtual bool equals(const StlMap& source) const { return this->valueMap == source.valueMap; } /** * {@inheritDoc} */ virtual bool equals(const Map& source) const { typename std::auto_ptr< Iterator > iterator(this->keySet().iterator()); while (iterator->hasNext()) { K key = iterator->next(); if (!this->containsKey(key)) { return false; } if (!(this->get(key) == source.get(key))) { return false; } } return true; } /** * {@inheritDoc} */ virtual void copy(const StlMap& source) { this->valueMap.clear(); this->valueMap.insert( source.valueMap.begin(), source.valueMap.end() ); } /** * {@inheritDoc} */ virtual void copy(const Map& source) { this->clear(); this->putAll(source); } /** * {@inheritDoc} */ virtual void clear() { valueMap.clear(); } /** * {@inheritDoc} */ virtual bool containsKey(const K& key) const { if (valueMap.empty()) { return false; } typename std::map::const_iterator iter; iter = valueMap.find(key); return iter != valueMap.end(); } /** * {@inheritDoc} */ virtual bool containsValue(const V& value) const { if (valueMap.empty()) { return false; } typename std::map::const_iterator iter = valueMap.begin(); for (; iter != valueMap.end(); ++iter) { if ((*iter).second == value) { return true; } } return false; } /** * {@inheritDoc} */ virtual bool isEmpty() const { return valueMap.empty(); } /** * {@inheritDoc} */ virtual int size() const { return (int)valueMap.size(); } /** * {@inheritDoc} */ virtual V& get(const K& key) { typename std::map::iterator iter; iter = valueMap.find(key); if (iter == valueMap.end()) { throw NoSuchElementException(__FILE__, __LINE__, "Key does not exist in map"); } return iter->second; } /** * {@inheritDoc} */ virtual const V& get(const K& key) const { typename std::map::const_iterator iter; iter = valueMap.find(key); if (iter == valueMap.end()) { throw NoSuchElementException(__FILE__, __LINE__, "Key does not exist in map"); } return iter->second; } /** * {@inheritDoc} */ virtual bool put(const K& key, const V& value) { bool result = false; if (this->containsKey(key)) { result = true; } valueMap[key] = value; modCount++; return result; } /** * {@inheritDoc} */ virtual bool put(const K& key, const V& value, V& oldValue) { bool result = false; if (this->containsKey(key)) { result = true; oldValue = valueMap[key]; } valueMap[key] = value; modCount++; return result; } /** * {@inheritDoc} */ virtual void putAll(const StlMap& other) { this->valueMap.insert(other.valueMap.begin(), other.valueMap.end()); this->modCount++; } /** * {@inheritDoc} */ virtual void putAll(const Map& other) { typename std::auto_ptr< Iterator > iterator(other.keySet().iterator()); while (iterator->hasNext()) { K key = iterator->next(); this->put(key, other.get(key)); } } /** * {@inheritDoc} */ virtual V remove(const K& key) { typename std::map::iterator iter = valueMap.find(key); if (iter == valueMap.end()) { throw NoSuchElementException( __FILE__, __LINE__, "Key is not present in this Map."); } V result = iter->second; valueMap.erase(iter); modCount++; return result; } virtual Set< MapEntry >& entrySet() { if (this->cachedEntrySet == NULL) { this->cachedEntrySet.reset(new StlMapEntrySet(this)); } return *(this->cachedEntrySet); } virtual const Set< MapEntry >& entrySet() const { if (this->cachedConstEntrySet == NULL) { this->cachedConstEntrySet.reset(new ConstStlMapEntrySet(this)); } return *(this->cachedConstEntrySet); } virtual Set& keySet() { if (this->cachedKeySet == NULL) { this->cachedKeySet.reset(new StlMapKeySet(this)); } return *(this->cachedKeySet); } virtual const Set& keySet() const { if (this->cachedConstKeySet == NULL) { this->cachedConstKeySet.reset(new ConstStlMapKeySet(this)); } return *(this->cachedConstKeySet); } virtual Collection& values() { if (this->cachedValueCollection == NULL) { this->cachedValueCollection.reset(new StlMapValueCollection(this)); } return *(this->cachedValueCollection); } virtual const Collection& values() const { if (this->cachedConstValueCollection == NULL) { this->cachedConstValueCollection.reset(new ConstStlMapValueCollection(this)); } return *(this->cachedConstValueCollection); } public: virtual void lock() { mutex.lock(); } virtual bool tryLock() { return mutex.tryLock(); } virtual void unlock() { mutex.unlock(); } virtual void wait() { mutex.wait(); } virtual void wait( long long millisecs ) { mutex.wait( millisecs ); } virtual void wait( long long millisecs, int nanos ) { mutex.wait( millisecs, nanos ); } virtual void notify() { mutex.notify(); } virtual void notifyAll() { mutex.notifyAll(); } }; }} #endif /*_DECAF_UTIL_STLMAP_H_*/