import { StringBuilder, cast_java_lang_StringBuilder } from '../../../java/lang/StringBuilder'; import { IndexOutOfBoundsException, cast_java_lang_IndexOutOfBoundsException } from '../../../java/lang/IndexOutOfBoundsException'; import { JavaString, cast_java_lang_String } from '../../../java/lang/JavaString'; import { Deque, cast_java_util_Deque } from '../../../java/util/Deque'; import { LinkedCollectionElement, cast_de_nrw_schule_svws_core_adt_collection_LinkedCollectionElement } from '../../../core/adt/collection/LinkedCollectionElement'; import { Comparator, cast_java_util_Comparator } from '../../../java/util/Comparator'; import { NullPointerException, cast_java_lang_NullPointerException } from '../../../java/lang/NullPointerException'; import { JavaIterator, cast_java_util_Iterator } from '../../../java/util/JavaIterator'; import { Collection, cast_java_util_Collection } from '../../../java/util/Collection'; import { Cloneable, cast_java_lang_Cloneable } from '../../../java/lang/Cloneable'; import { JavaObject, cast_java_lang_Object } from '../../../java/lang/JavaObject'; import { LinkedCollectionDescendingIterator, cast_de_nrw_schule_svws_core_adt_collection_LinkedCollectionDescendingIterator } from '../../../core/adt/collection/LinkedCollectionDescendingIterator'; import { LinkedCollectionIterator, cast_de_nrw_schule_svws_core_adt_collection_LinkedCollectionIterator } from '../../../core/adt/collection/LinkedCollectionIterator'; import { Arrays, cast_java_util_Arrays } from '../../../java/util/Arrays'; import { NoSuchElementException, cast_java_util_NoSuchElementException } from '../../../java/util/NoSuchElementException'; import { CloneNotSupportedException, cast_java_lang_CloneNotSupportedException } from '../../../java/lang/CloneNotSupportedException'; export class LinkedCollection extends JavaObject implements Deque, Cloneable { _head : LinkedCollectionElement | null = null; _tail : LinkedCollectionElement | null = null; private _size : number = 0; _modCount : number = 0; /** * Erzeugt eine neue LinkedCollection. */ public constructor(); /** * Erzeugt eine neue LinkedCollection als Kopie der übergebenen * LinkedCollection * * @param c die LinkedCollection, die kopiert wird */ public constructor(c : LinkedCollection | null); /** * Implementation for method overloads of 'constructor' */ public constructor(__param0? : LinkedCollection | null) { super(); if ((typeof __param0 === "undefined")) { this._head = null; this._tail = null; this._size = 0; this._modCount = 0; } else if (((typeof __param0 !== "undefined") && ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.collection.LinkedCollection'))) || (__param0 === null))) { let c : LinkedCollection | null = cast_de_nrw_schule_svws_core_adt_collection_LinkedCollection(__param0); this._size = 0; this._modCount = 0; let iter : JavaIterator = c.iterator(); while (iter.hasNext()) this.add(iter.next()); this._modCount = c._modCount; } else throw new Error('invalid method overload'); } public size() : number { return this._size; } public isEmpty() : boolean { return (this._head === null) ? true : false; } public contains(obj : unknown | null) : boolean { if (this.isEmpty()) return false; let iter : JavaIterator = this.iterator(); while (iter.hasNext()) if (JavaObject.equalsTranspiler(iter.next(), (obj))) return true; return false; } public iterator() : JavaIterator { return new LinkedCollectionIterator(this); } public toArray() : Array; public toArray(a : Array) : Array; /** * Implementation for method overloads of 'toArray' */ public toArray(__param0? : Array) : Array | Array { if ((typeof __param0 === "undefined")) { if (this._size === 0) return Array(0).fill(null); let array : Array = Array(this._size).fill(null); let iter : JavaIterator = this.iterator(); for (let i : number = 0; i < this._size; i++){ array[i] = iter.next(); } return array; } else if (((typeof __param0 !== "undefined") && Array.isArray(__param0))) { let a : Array = __param0; if (a.length < this._size) return this.toArray(); let iter : JavaIterator = this.iterator(); for (let i : number = 0; i < this._size; i++){ let e : E = iter.next(); a[i] = e as unknown as T; } Arrays.fill(a, this._size, a.length, null); return a; } else throw new Error('invalid method overload'); } public add(e : E | null) : boolean { if (e === null) return false; let newElem : LinkedCollectionElement = new LinkedCollectionElement(e, null, null); if ((this._head === null) || (this._tail === null)) { this._head = newElem; this._tail = newElem; this._size++; this._modCount++; return true; } newElem.setPrev(this._tail); this._tail.setNext(newElem); this._tail = newElem; this._size++; this._modCount++; return true; } /** * Entfernt das übergebene Element. * * @param elem das zu entfernende Element * * @return true, falls das Element erfolgreich entfernt wurde, und false, falls null übergeben wurde. */ private removeElement(elem : LinkedCollectionElement | null) : boolean { if (elem === null) return false; let prev : LinkedCollectionElement | null = elem.getPrev(); let next : LinkedCollectionElement | null = elem.getNext(); if (this._size === 1) { this._head = null; this._tail = null; } else if (JavaObject.equalsTranspiler(elem, (this._head))) { if (next === null) throw new NullPointerException() this._head = next; next.setPrev(null); } else if (JavaObject.equalsTranspiler(elem, (this._tail))) { if (prev === null) throw new NullPointerException() this._tail = prev; prev.setNext(null); } else { if ((next === null) || (prev === null)) throw new NullPointerException() next.setPrev(prev); prev.setNext(next); } this._size--; this._modCount++; return true; } public remove(obj : unknown | null) : boolean; public remove() : E; /** * Implementation for method overloads of 'remove' */ public remove(__param0? : null | unknown) : E | boolean { if (((typeof __param0 !== "undefined") && ((__param0 instanceof Object) || ((__param0 instanceof JavaObject) && (__param0.isTranspiledInstanceOf('java.lang.Object')))) || (__param0 === null))) { let obj : unknown | null = (__param0 instanceof JavaObject) ? cast_java_lang_Object(__param0) : __param0; if (this.isEmpty()) return false; return this.removeElement(this.findFirst(obj)); } else if ((typeof __param0 === "undefined")) { let value : E | null = this.poll(); if (value === null) throw new NoSuchElementException() return value; } else throw new Error('invalid method overload'); } public containsAll(c : Collection | null) : boolean { if ((c === null) || (this as unknown === c as unknown)) return true; for (let o of c) if (!this.contains(o)) return false; return true; } public addAll(c : Collection | null) : boolean { if ((c === null) || (c.size() === 0)) return false; if (((c instanceof JavaObject) && (c.isTranspiledInstanceOf('de.nrw.schule.svws.core.adt.collection.LinkedCollection')))) { let coll : LinkedCollection = cast_de_nrw_schule_svws_core_adt_collection_LinkedCollection(c); if ((coll._tail === null) || (coll._head === null)) throw new NullPointerException() let last : LinkedCollectionElement = coll._tail; let current : LinkedCollectionElement | null = coll._head; this.add(current.getValue()); while (current as unknown !== last as unknown) { current = current.getNext(); if (current === null) throw new NullPointerException() this.add(current.getValue()); } return true; } let result : boolean = false; for (let elem of c) { if (this.add(elem)) result = true; } return result; } public removeAll(c : Collection | null) : boolean { if (c === null) return false; if (this as unknown === c as unknown) { if (this.size() === 0) return false; this.clear(); return true; } let result : boolean = false; for (let o of c) { if (this.remove(o)) { result = true; while (this.remove(o)) ; } } return result; } public retainAll(c : Collection | null) : boolean { if ((this as unknown === c as unknown) || (this._head === null)) return false; if (c === null) { this.clear(); return true; } let iter : JavaIterator = this.iterator(); let tmp : LinkedCollection = new LinkedCollection(); while (iter.hasNext()) { let elem : E = iter.next(); if (!c.contains(elem)) tmp.add(elem); } if (tmp.isEmpty()) return false; return this.removeAll(tmp); } public clear() : void { this._head = null; this._tail = null; this._size = 0; this._modCount++; } public hashCode() : number { let hashCode : number = 1; for (let e of this) hashCode = 31 * hashCode + (e === null ? 0 : JavaObject.getTranspilerHashCode(e)); return hashCode; } public equals(obj : unknown | null) : boolean { if ((obj === null) || (!(((obj instanceof JavaObject) && (obj.isTranspiledInstanceOf('java.util.Collection')))))) return false; let other : Collection = cast_java_util_Collection(obj); if (this._size !== other.size()) return false; let iter : JavaIterator = this.iterator(); let otherIter : JavaIterator = other.iterator(); while (iter.hasNext()) { if (!JavaObject.equalsTranspiler(iter.next(), (otherIter.next()))) return false; } return true; } public clone() : unknown { return new LinkedCollection(this); } public toString() : String { let sb : StringBuilder = new StringBuilder(); sb.append("["); let iter : JavaIterator = this.iterator(); while (iter.hasNext()) { sb.append(iter.next()); if (iter.hasNext() === true) sb.append(", "); } sb.append("]"); return sb.toString(); } /** * Diese Methode ist eine Hilfsmethode für die Methode sort(). Sie mischt die beiden über die prev-Zeiger * verketteten Listen left und right zu einer kombinierten, über die prev-Zeiger verketteten Liste. * * @param comparator ein {@link Comparator} zum Vergleichen zweier Elemente * @param left die erste sortierte Liste * @param right die zweite sortierte Liste * * @return die kombinierte sortierte Liste */ private merge(comparator : Comparator, left : LinkedCollectionElement, right : LinkedCollectionElement) : LinkedCollectionElement { let headTo : LinkedCollectionElement | null; let headFrom : LinkedCollectionElement | null; if (comparator.compare(left.getValue(), right.getValue()) > 0) { headFrom = left; headTo = right; } else { headFrom = right; headTo = left; } let target : LinkedCollectionElement = headTo; while (headFrom !== null) { let current : LinkedCollectionElement = headFrom; headFrom = headFrom.getPrev(); let targetPrev : LinkedCollectionElement | null = target.getPrev(); while ((targetPrev !== null) && (comparator.compare(targetPrev.getValue(), current.getValue()) < 0)) { target = targetPrev; targetPrev = target.getPrev(); } if (targetPrev === null) { target.setPrev(current); break; } current.setPrev(targetPrev); target.setPrev(current); } return headTo; } /** * Sortiert den Inhalte dieser Liste mithilfe des übergebenen {@link Comparator}-Objekts. * * @param comparator ein {@link Comparator} zum Vergleichen zweier Elemente * * @return true, falls eine Sortierung erfolgreich war */ public sort(comparator : Comparator | null) : boolean { if (comparator === null) return false; if ((this._size <= 1) || (this._head === null) || (this._tail === null)) return true; this._modCount++; for (let current : LinkedCollectionElement | null = this._head; current !== null; current = current.getNext()) current.setPrev(null); while (this._head !== null) { let left : LinkedCollectionElement = this._head; let right : LinkedCollectionElement | null = left.getNext(); if (right === null) throw new NullPointerException() this._head = right.getNext(); left.setNext(null); right.setNext(null); let sorted : LinkedCollectionElement = this.merge(comparator, left, right); this._tail.setNext(sorted); this._tail = sorted; } this._head = this._tail; this._tail.setNext(this._tail.getPrev()); while (this._tail.getPrev() !== null) { this._tail = this._tail.getPrev(); if (this._tail === null) throw new NullPointerException() this._tail.setNext(this._tail.getPrev()); } this._head.setPrev(null); let current : LinkedCollectionElement = this._head; let next : LinkedCollectionElement | null = current.getNext(); while (next !== null) { next.setPrev(current); current = next; next = current.getNext(); } this._modCount++; return true; } /** * Sucht das Element an der Stelle Index. * * @param index die Stelle des gesuchten Elements * * @return das Element an der gesuchten Stelle * * @throws IndexOutOfBoundsException wenn der Index nicht im gültigen Bereich liegt (index >= 0) && (index < size())) */ private find(index : number) : LinkedCollectionElement { if ((index < 0) || (index >= this._size)) throw new IndexOutOfBoundsException() let current : LinkedCollectionElement | null = this._head; for (let i : number = 0; (current !== null); i++, current = current.getNext()) if (i === index) return current; throw new IndexOutOfBoundsException() } /** * Sucht ein LinkedCollectionElement in der Collection mit dem Wert obj * und gibt es zurück * * @param obj der Wert der in der LinkedCollection gesucht werden soll * * @return ein LinkedCollectionElement falls der Wert in der Collection * enthalten ist und das Element dessen , ansonsten null */ private findFirst(obj : unknown | null) : LinkedCollectionElement | null { if (obj === null) return null; let current : LinkedCollectionElement | null = this._head; while (current !== null) { if (JavaObject.equalsTranspiler(current.getValue(), (obj))) return current; current = current.getNext(); } return null; } /** * Sucht ein LinkedCollectionElement in der Collection mit dem Wert obj * und gibt es zurück * * @param obj der Wert der in der LinkedCollection gesucht werden soll * * @return ein LinkedCollectionElement falls der Wert in der Collection * enthalten ist und das Element dessen, ansonsten null */ private findLast(obj : unknown | null) : LinkedCollectionElement | null { if (obj === null) return null; let current : LinkedCollectionElement | null = this._tail; while (current !== null) { if (JavaObject.equalsTranspiler(current.getValue(), (obj))) return current; current = current.getPrev(); } return null; } public offer(e : E | null) : boolean { return this.add(e); } public poll() : E | null { if (this._head === null) return null; let value : E = this._head.getValue(); this._head = this._head.getNext(); if (this._head === null) this._tail = null; else this._head.setPrev(null); this._size--; this._modCount++; return value; } public element() : E { if (this._head === null) throw new NoSuchElementException() return this._head.getValue(); } public peek() : E | null { return (this._head === null) ? null : this._head.getValue(); } public addFirst(e : E | null) : void { if (e === null) throw new NullPointerException() let newElem : LinkedCollectionElement = new LinkedCollectionElement(e, null, null); if ((this._head === null) || (this._tail === null)) { this._head = newElem; this._tail = newElem; } else { newElem.setNext(this._head); this._head.setPrev(newElem); this._head = newElem; } this._size++; this._modCount++; } public addLast(e : E | null) : void { if (e === null) throw new NullPointerException() this.add(e); } public offerFirst(e : E | null) : boolean { this.addFirst(e); return true; } public offerLast(e : E | null) : boolean { this.addLast(e); return true; } public removeFirst() : E { let value : E | null = this.poll(); if (value === null) throw new NoSuchElementException() return value; } public removeLast() : E { let value : E | null = this.pollLast(); if (value === null) throw new NoSuchElementException() return value; } public pollFirst() : E | null { return this.poll(); } public pollLast() : E | null { if (this._tail === null) return null; let value : E = this._tail.getValue(); this._tail = this._tail.getPrev(); if (this._tail === null) this._head = null; else this._tail.setNext(null); this._size--; this._modCount++; return value; } public getFirst() : E { if (this._head === null) throw new NoSuchElementException() return this._head.getValue(); } public getLast() : E { if (this._tail === null) throw new NoSuchElementException() return this._tail.getValue(); } public peekFirst() : E | null { return (this._head === null) ? null : this._head.getValue(); } public peekLast() : E | null { return (this._tail === null) ? null : this._tail.getValue(); } public removeFirstOccurrence(obj : unknown | null) : boolean { if (this.isEmpty()) return false; return this.removeElement(this.findFirst(obj)); } public removeLastOccurrence(obj : unknown | null) : boolean { if (this.isEmpty()) return false; return this.removeElement(this.findLast(obj)); } public push(e : E) : void { this.addFirst(e); } public pop() : E { let value : E | null = this.poll(); if (value === null) throw new NoSuchElementException() return value; } public descendingIterator() : JavaIterator { return new LinkedCollectionDescendingIterator(this); } /** * Gibt den Wert an der Stelle index zurück. * * @param index der Index * * @return der Wert * * @throws IndexOutOfBoundsException wenn der Index nicht im gültigen Bereich liegt {@code (index >= 0) && (index < size()))} */ public get(index : number) : E { return this.find(index).getValue(); } /** * Ersetzt den Wert an der Stelle index mit dem neuen übergebenen Wert. * * @param index die Stelle, wo der Wert ersetzt werden soll * @param element der neue Wert für die Stelle * * @return der alte Wert an der Stelle * * @throws IndexOutOfBoundsException wenn der Index nicht im gültigen Bereich liegt {@code (index >= 0) && (index < size()))} */ public set(index : number, element : E) : E { return this.find(index).setValue(element); } isTranspiledInstanceOf(name : string): boolean { return ['java.lang.Cloneable', 'java.util.Collection', 'java.util.Queue', 'java.util.Deque', 'java.lang.Iterable', 'de.nrw.schule.svws.core.adt.collection.LinkedCollection'].includes(name); } public [Symbol.iterator](): Iterator { let iter : JavaIterator = this.iterator(); const result : Iterator = { next() : IteratorResult { if (iter.hasNext()) return { value : iter.next(), done : false }; return { value : null, done : true }; } }; return result; } } export function cast_de_nrw_schule_svws_core_adt_collection_LinkedCollection(obj : unknown) : LinkedCollection { return obj as LinkedCollection; }