PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Java.NET/JavApi Commons collections (Apache Port)/org.apache.commons.collections.map.ListOrderedMap.cs

https://github.com/gadfly/nofs
C# | 807 lines | 482 code | 81 blank | 244 comment | 33 complexity | 1a68616ffb5a81f0cee2b9454ae54598 MD5 | raw file
  1. /*
  2. * Licensed under the Apache License, Version 2.0 (the "License");
  3. * you may not use this file except in compliance with the License.
  4. * You may obtain a copy of the License at
  5. *
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. *
  14. */
  15. using System;
  16. using java = biz.ritter.javapi;
  17. using org.apache.commons.collections;
  18. using org.apache.commons.collections.iterators;
  19. using org.apache.commons.collections.keyvalue;
  20. using org.apache.commons.collections.list;
  21. namespace org.apache.commons.collections.map
  22. {
  23. /**
  24. * Decorates a <code>Map</code> to ensure that the order of addition is retained
  25. * using a <code>List</code> to maintain order.
  26. * <p>
  27. * The order will be used via the iterators and toArray methods on the views.
  28. * The order is also returned by the <code>MapIterator</code>.
  29. * The <code>orderedMapIterator()</code> method accesses an iterator that can
  30. * iterate both forwards and backwards through the map.
  31. * In addition, non-interface methods are provided to access the map by index.
  32. * <p>
  33. * If an object is added to the Map for a second time, it will remain in the
  34. * original position in the iteration.
  35. * <p>
  36. * <strong>Note that ListOrderedMap is not synchronized and is not thread-safe.</strong>
  37. * If you wish to use this map from multiple threads concurrently, you must use
  38. * appropriate synchronization. The simplest approach is to wrap this map
  39. * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw
  40. * exceptions when accessed by concurrent threads without synchronization.
  41. * <p>
  42. * This class is java.io.Serializable from Commons Collections 3.1.
  43. *
  44. * @since Commons Collections 3.0
  45. * @version $Revision$ $Date$
  46. *
  47. * @author Henri Yandell
  48. * @author Stephen Colebourne
  49. * @author Matt Benson
  50. */
  51. [Serializable]
  52. public class ListOrderedMap
  53. : AbstractMapDecorator
  54. , OrderedMap, java.io.Serializable
  55. {
  56. /** Serialization version */
  57. private static readonly long serialVersionUID = 2728177751851003750L;
  58. /** Internal list to hold the sequence of objects */
  59. protected readonly java.util.List<Object> insertOrder = new java.util.ArrayList<Object>();
  60. /**
  61. * Factory method to create an ordered map.
  62. * <p>
  63. * An <code>ArrayList</code> is used to retain order.
  64. *
  65. * @param map the map to decorate, must not be null
  66. * @throws IllegalArgumentException if map is null
  67. */
  68. public static OrderedMap decorate(java.util.Map<Object, Object> map)
  69. {
  70. return new ListOrderedMap(map);
  71. }
  72. //-----------------------------------------------------------------------
  73. /**
  74. * Constructs a new empty <code>ListOrderedMap</code> that decorates
  75. * a <code>HashMap</code>.
  76. *
  77. * @since Commons Collections 3.1
  78. */
  79. public ListOrderedMap() :
  80. this(new java.util.HashMap<Object, Object>())
  81. {
  82. }
  83. /**
  84. * Constructor that wraps (not copies).
  85. *
  86. * @param map the map to decorate, must not be null
  87. * @throws IllegalArgumentException if map is null
  88. */
  89. protected ListOrderedMap(java.util.Map<Object, Object> map) :
  90. base(map)
  91. {
  92. insertOrder.addAll(getMap().keySet());
  93. }
  94. //-----------------------------------------------------------------------
  95. /**
  96. * Write the map out using a custom routine.
  97. *
  98. * @param out the output stream
  99. * @throws IOException
  100. * @since Commons Collections 3.1
  101. */
  102. private void writeObject(java.io.ObjectOutputStream outJ)
  103. {//throws IOException {
  104. outJ.defaultWriteObject();
  105. outJ.writeObject(map);
  106. }
  107. /**
  108. * Read the map in using a custom routine.
  109. *
  110. * @param in the input stream
  111. * @throws IOException
  112. * @throws ClassNotFoundException
  113. * @since Commons Collections 3.1
  114. */
  115. private void readObject(java.io.ObjectInputStream inJ)
  116. {//throws IOException, ClassNotFoundException {
  117. inJ.defaultReadObject();
  118. map = (java.util.Map<Object, Object>)inJ.readObject();
  119. }
  120. // Implement OrderedMap
  121. //-----------------------------------------------------------------------
  122. public virtual MapIterator mapIterator()
  123. {
  124. return orderedMapIterator();
  125. }
  126. public virtual OrderedMapIterator orderedMapIterator()
  127. {
  128. return new ListOrderedMapIterator(this);
  129. }
  130. /**
  131. * Gets the first key in this map by insert order.
  132. *
  133. * @return the first key currently in this map
  134. * @throws NoSuchElementException if this map is empty
  135. */
  136. public virtual Object firstKey()
  137. {
  138. if (size() == 0)
  139. {
  140. throw new java.util.NoSuchElementException("Map is empty");
  141. }
  142. return insertOrder.get(0);
  143. }
  144. /**
  145. * Gets the last key in this map by insert order.
  146. *
  147. * @return the last key currently in this map
  148. * @throws NoSuchElementException if this map is empty
  149. */
  150. public virtual Object lastKey()
  151. {
  152. if (size() == 0)
  153. {
  154. throw new java.util.NoSuchElementException("Map is empty");
  155. }
  156. return insertOrder.get(size() - 1);
  157. }
  158. /**
  159. * Gets the next key to the one specified using insert order.
  160. * This method performs a list search to find the key and is O(n).
  161. *
  162. * @param key the key to find previous for
  163. * @return the next key, null if no match or at start
  164. */
  165. public virtual Object nextKey(Object key)
  166. {
  167. int index = insertOrder.indexOf(key);
  168. if (index >= 0 && index < size() - 1)
  169. {
  170. return insertOrder.get(index + 1);
  171. }
  172. return null;
  173. }
  174. /**
  175. * Gets the previous key to the one specified using insert order.
  176. * This method performs a list search to find the key and is O(n).
  177. *
  178. * @param key the key to find previous for
  179. * @return the previous key, null if no match or at start
  180. */
  181. public virtual Object previousKey(Object key)
  182. {
  183. int index = insertOrder.indexOf(key);
  184. if (index > 0)
  185. {
  186. return insertOrder.get(index - 1);
  187. }
  188. return null;
  189. }
  190. //-----------------------------------------------------------------------
  191. public override Object put(Object key, Object value)
  192. {
  193. if (getMap().containsKey(key))
  194. {
  195. // re-adding doesn't change order
  196. return getMap().put(key, value);
  197. }
  198. else
  199. {
  200. // first add, so add to both map and list
  201. Object result = getMap().put(key, value);
  202. insertOrder.add(key);
  203. return result;
  204. }
  205. }
  206. public override void putAll(java.util.Map<Object, Object> map)
  207. {
  208. for (java.util.Iterator<java.util.MapNS.Entry<Object, Object>> it = map.entrySet().iterator(); it.hasNext(); )
  209. {
  210. java.util.MapNS.Entry<Object, Object> entry = it.next();
  211. put(entry.getKey(), entry.getValue());
  212. }
  213. }
  214. public override Object remove(Object key)
  215. {
  216. Object result = getMap().remove(key);
  217. insertOrder.remove(key);
  218. return result;
  219. }
  220. public override void clear()
  221. {
  222. getMap().clear();
  223. insertOrder.clear();
  224. }
  225. //-----------------------------------------------------------------------
  226. /**
  227. * Gets a view over the keys in the map.
  228. * <p>
  229. * The Collection will be ordered by object insertion into the map.
  230. *
  231. * @see #keyList()
  232. * @return the fully modifiable collection view over the keys
  233. */
  234. public override java.util.Set<Object> keySet()
  235. {
  236. return new KeySetView(this);
  237. }
  238. /**
  239. * Gets a view over the keys in the map as a List.
  240. * <p>
  241. * The List will be ordered by object insertion into the map.
  242. * The List is unmodifiable.
  243. *
  244. * @see #keySet()
  245. * @return the unmodifiable list view over the keys
  246. * @since Commons Collections 3.2
  247. */
  248. public virtual java.util.List<Object> keyList()
  249. {
  250. return UnmodifiableList.decorate(insertOrder);
  251. }
  252. /**
  253. * Gets a view over the values in the map.
  254. * <p>
  255. * The Collection will be ordered by object insertion into the map.
  256. * <p>
  257. * From Commons Collections 3.2, this Collection can be cast
  258. * to a list, see {@link #valueList()}
  259. *
  260. * @see #valueList()
  261. * @return the fully modifiable collection view over the values
  262. */
  263. public override java.util.Collection<Object> values()
  264. {
  265. return new ValuesView(this);
  266. }
  267. /**
  268. * Gets a view over the values in the map as a List.
  269. * <p>
  270. * The List will be ordered by object insertion into the map.
  271. * The List supports remove and set, but does not support add.
  272. *
  273. * @see #values()
  274. * @return the partially modifiable list view over the values
  275. * @since Commons Collections 3.2
  276. */
  277. public virtual java.util.List<Object> valueList()
  278. {
  279. return new ValuesView(this);
  280. }
  281. /**
  282. * Gets a view over the entries in the map.
  283. * <p>
  284. * The Set will be ordered by object insertion into the map.
  285. *
  286. * @return the fully modifiable set view over the entries
  287. */
  288. public new java.util.Set<Object> entrySet()
  289. {
  290. return new EntrySetView(this, this.insertOrder);
  291. }
  292. //-----------------------------------------------------------------------
  293. /**
  294. * Returns the Map as a string.
  295. *
  296. * @return the Map as a String
  297. */
  298. public override String ToString()
  299. {
  300. if (isEmpty())
  301. {
  302. return "{}";
  303. }
  304. java.lang.StringBuffer buf = new java.lang.StringBuffer();
  305. buf.append('{');
  306. bool first = true;
  307. java.util.Iterator<Object> it = entrySet().iterator();
  308. while (it.hasNext())
  309. {
  310. java.util.MapNS.Entry<Object, Object> entry = (java.util.MapNS.Entry<Object, Object>)it.next();
  311. Object key = entry.getKey();
  312. Object value = entry.getValue();
  313. if (first)
  314. {
  315. first = false;
  316. }
  317. else
  318. {
  319. buf.append(", ");
  320. }
  321. buf.append(key == this ? "(this Map)" : key);
  322. buf.append('=');
  323. buf.append(value == this ? "(this Map)" : value);
  324. }
  325. buf.append('}');
  326. return buf.toString();
  327. }
  328. //-----------------------------------------------------------------------
  329. /**
  330. * Gets the key at the specified index.
  331. *
  332. * @param index the index to retrieve
  333. * @return the key at the specified index
  334. * @throws IndexOutOfBoundsException if the index is invalid
  335. */
  336. public virtual Object get(int index)
  337. {
  338. return insertOrder.get(index);
  339. }
  340. /**
  341. * Gets the value at the specified index.
  342. *
  343. * @param index the index to retrieve
  344. * @return the key at the specified index
  345. * @throws IndexOutOfBoundsException if the index is invalid
  346. */
  347. public virtual Object getValue(int index)
  348. {
  349. return get(insertOrder.get(index));
  350. }
  351. /**
  352. * Gets the index of the specified key.
  353. *
  354. * @param key the key to find the index of
  355. * @return the index, or -1 if not found
  356. */
  357. public virtual int indexOf(Object key)
  358. {
  359. return insertOrder.indexOf(key);
  360. }
  361. /**
  362. * Sets the value at the specified index.
  363. *
  364. * @param index the index of the value to set
  365. * @return the previous value at that index
  366. * @throws IndexOutOfBoundsException if the index is invalid
  367. * @since Commons Collections 3.2
  368. */
  369. public virtual Object setValue(int index, Object value)
  370. {
  371. Object key = insertOrder.get(index);
  372. return put(key, value);
  373. }
  374. /**
  375. * Puts a key-value mapping into the map at the specified index.
  376. * <p>
  377. * If the map already contains the key, then the original mapping
  378. * is removed and the new mapping added at the specified index.
  379. * The remove may change the effect of the index. The index is
  380. * always calculated relative to the original state of the map.
  381. * <p>
  382. * Thus the steps are: (1) remove the existing key-value mapping,
  383. * then (2) insert the new key-value mapping at the position it
  384. * would have been inserted had the remove not ocurred.
  385. *
  386. * @param index the index at which the mapping should be inserted
  387. * @param key the key
  388. * @param value the value
  389. * @return the value previously mapped to the key
  390. * @throws IndexOutOfBoundsException if the index is out of range
  391. * @since Commons Collections 3.2
  392. */
  393. public virtual Object put(int index, Object key, Object value)
  394. {
  395. java.util.Map<Object, Object> m = getMap();
  396. if (m.containsKey(key))
  397. {
  398. Object result = m.remove(key);
  399. int pos = insertOrder.indexOf(key);
  400. insertOrder.remove(pos);
  401. if (pos < index)
  402. {
  403. index--;
  404. }
  405. insertOrder.add(index, key);
  406. m.put(key, value);
  407. return result;
  408. }
  409. else
  410. {
  411. insertOrder.add(index, key);
  412. m.put(key, value);
  413. return null;
  414. }
  415. }
  416. /**
  417. * Removes the element at the specified index.
  418. *
  419. * @param index the index of the object to remove
  420. * @return the removed value, or <code>null</code> if none existed
  421. * @throws IndexOutOfBoundsException if the index is invalid
  422. */
  423. public Object remove(int index)
  424. {
  425. return remove(get(index));
  426. }
  427. /**
  428. * Gets an unmodifiable List view of the keys which changes as the map changes.
  429. * <p>
  430. * The returned list is unmodifiable because changes to the values of
  431. * the list (using {@link java.util.ListIterator#set(Object)}) will
  432. * effectively remove the value from the list and reinsert that value at
  433. * the end of the list, which is an unexpected side effect of changing the
  434. * value of a list. This occurs because changing the key, changes when the
  435. * mapping is added to the map and thus where it appears in the list.
  436. * <p>
  437. * An alternative to this method is to use the better named
  438. * {@link #keyList()} or {@link #keySet()}.
  439. *
  440. * @see #keyList()
  441. * @see #keySet()
  442. * @return The ordered list of keys.
  443. */
  444. public virtual java.util.List<Object> asList()
  445. {
  446. return keyList();
  447. }
  448. //-----------------------------------------------------------------------
  449. class ValuesView : java.util.AbstractList<Object>
  450. {
  451. private readonly ListOrderedMap parent;
  452. internal ValuesView(ListOrderedMap parent)
  453. : base()
  454. {
  455. this.parent = parent;
  456. }
  457. public override int size()
  458. {
  459. return this.parent.size();
  460. }
  461. public override bool contains(Object value)
  462. {
  463. return this.parent.containsValue(value);
  464. }
  465. public override void clear()
  466. {
  467. this.parent.clear();
  468. }
  469. public override java.util.Iterator<Object> iterator()
  470. {
  471. return new IAC_Iterator(parent.entrySet().iterator());
  472. }
  473. public override Object get(int index)
  474. {
  475. return this.parent.getValue(index);
  476. }
  477. public override Object set(int index, Object value)
  478. {
  479. return this.parent.setValue(index, value);
  480. }
  481. public override Object remove(int index)
  482. {
  483. return this.parent.remove(index);
  484. }
  485. }
  486. class IAC_Iterator : AbstractIteratorDecorator
  487. {
  488. public IAC_Iterator(java.util.Iterator<Object> toDecorate)
  489. : base(toDecorate)
  490. {
  491. }
  492. public override Object next()
  493. {
  494. //! todo (this line is expected): return iterator.next().getValue();
  495. Object obj = iterator.next();
  496. Object result = obj.GetType().GetMethod("getValue").Invoke(obj, null);
  497. return result;
  498. }
  499. }
  500. //-----------------------------------------------------------------------
  501. class KeySetView : java.util.AbstractSet<Object>
  502. {
  503. private readonly ListOrderedMap parent;
  504. internal KeySetView(ListOrderedMap parent)
  505. : base()
  506. {
  507. this.parent = parent;
  508. }
  509. public override int size()
  510. {
  511. return this.parent.size();
  512. }
  513. public override bool contains(Object value)
  514. {
  515. return this.parent.containsKey(value);
  516. }
  517. public override void clear()
  518. {
  519. this.parent.clear();
  520. }
  521. public override java.util.Iterator<Object> iterator()
  522. {
  523. return new IAC_Iterator(parent.entrySet().iterator());
  524. }
  525. }
  526. //-----------------------------------------------------------------------
  527. class EntrySetView : java.util.AbstractSet<Object>
  528. {
  529. private readonly ListOrderedMap parent;
  530. private readonly java.util.List<Object> insertOrder;
  531. private java.util.Set<java.util.MapNS.Entry<Object, Object>> entrySet;
  532. public EntrySetView(ListOrderedMap parent, java.util.List<Object> insertOrder)
  533. : base()
  534. {
  535. this.parent = parent;
  536. this.insertOrder = insertOrder;
  537. }
  538. private java.util.Set<Object> getEntrySet()
  539. {
  540. if (entrySet == null)
  541. {
  542. entrySet = parent.getMap().entrySet();
  543. }
  544. return (java.util.Set<Object>)entrySet;
  545. }
  546. public override int size()
  547. {
  548. return this.parent.size();
  549. }
  550. public override bool isEmpty()
  551. {
  552. return this.parent.isEmpty();
  553. }
  554. public override bool contains(Object obj)
  555. {
  556. return getEntrySet().contains(obj);
  557. }
  558. public override bool containsAll(java.util.Collection<Object> coll)
  559. {
  560. return getEntrySet().containsAll(coll);
  561. }
  562. public override bool remove(Object obj)
  563. {
  564. if (obj is java.util.MapNS.Entry<Object, Object> == false)
  565. {
  566. return false;
  567. }
  568. if (getEntrySet().contains(obj))
  569. {
  570. Object key = ((java.util.MapNS.Entry<Object, Object>)obj).getKey();
  571. parent.remove(key);
  572. return true;
  573. }
  574. return false;
  575. }
  576. public override void clear()
  577. {
  578. this.parent.clear();
  579. }
  580. public override bool Equals(Object obj)
  581. {
  582. if (obj == this)
  583. {
  584. return true;
  585. }
  586. return getEntrySet().equals(obj);
  587. }
  588. public override int GetHashCode()
  589. {
  590. return getEntrySet().GetHashCode();
  591. }
  592. public String toString()
  593. {
  594. return getEntrySet().toString();
  595. }
  596. public override java.util.Iterator<Object> iterator()
  597. {
  598. return new ListOrderedIterator(parent, insertOrder);
  599. }
  600. }
  601. //-----------------------------------------------------------------------
  602. class ListOrderedIterator : AbstractIteratorDecorator
  603. {
  604. private readonly ListOrderedMap parent;
  605. private Object last = null;
  606. internal ListOrderedIterator(ListOrderedMap parent, java.util.List<Object> insertOrder)
  607. : base(insertOrder.iterator())
  608. {
  609. this.parent = parent;
  610. }
  611. public override Object next()
  612. {
  613. last = base.next();
  614. return new ListOrderedMapEntry(parent, last);
  615. }
  616. public override void remove()
  617. {
  618. base.remove();
  619. parent.getMap().remove(last);
  620. }
  621. }
  622. //-----------------------------------------------------------------------
  623. class ListOrderedMapEntry : AbstractMapEntry
  624. {
  625. private readonly ListOrderedMap parent;
  626. internal ListOrderedMapEntry(ListOrderedMap parent, Object key)
  627. : base(key, null)
  628. {
  629. this.parent = parent;
  630. }
  631. public override Object getValue()
  632. {
  633. return parent.get(key);
  634. }
  635. public override Object setValue(Object value)
  636. {
  637. return parent.getMap().put(key, value);
  638. }
  639. }
  640. //-----------------------------------------------------------------------
  641. class ListOrderedMapIterator : OrderedMapIterator, ResettableIterator
  642. {
  643. private readonly ListOrderedMap parent;
  644. private java.util.ListIterator<Object> iterator;
  645. private Object last = null;
  646. private bool readable = false;
  647. internal ListOrderedMapIterator(ListOrderedMap parent)
  648. : base()
  649. {
  650. this.parent = parent;
  651. this.iterator = parent.insertOrder.listIterator();
  652. }
  653. public virtual bool hasNext()
  654. {
  655. return iterator.hasNext();
  656. }
  657. public virtual Object next()
  658. {
  659. last = iterator.next();
  660. readable = true;
  661. return last;
  662. }
  663. public virtual bool hasPrevious()
  664. {
  665. return iterator.hasPrevious();
  666. }
  667. public virtual Object previous()
  668. {
  669. last = iterator.previous();
  670. readable = true;
  671. return last;
  672. }
  673. public virtual void remove()
  674. {
  675. if (readable == false)
  676. {
  677. throw new java.lang.IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
  678. }
  679. iterator.remove();
  680. parent.map.remove(last);
  681. readable = false;
  682. }
  683. public virtual Object getKey()
  684. {
  685. if (readable == false)
  686. {
  687. throw new java.lang.IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
  688. }
  689. return last;
  690. }
  691. public virtual Object getValue()
  692. {
  693. if (readable == false)
  694. {
  695. throw new java.lang.IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
  696. }
  697. return parent.get(last);
  698. }
  699. public virtual Object setValue(Object value)
  700. {
  701. if (readable == false)
  702. {
  703. throw new java.lang.IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
  704. }
  705. return parent.map.put(last, value);
  706. }
  707. public virtual void reset()
  708. {
  709. iterator = parent.insertOrder.listIterator();
  710. last = null;
  711. readable = false;
  712. }
  713. public override String ToString()
  714. {
  715. if (readable == true)
  716. {
  717. return "Iterator[" + getKey() + "=" + getValue() + "]";
  718. }
  719. else
  720. {
  721. return "Iterator[]";
  722. }
  723. }
  724. }
  725. }
  726. }