working java,python, js then added rust, then rewired java to j
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
Copyright (c) 2011-2022 Reliancy LLC
|
||||
|
||||
Licensed under the GNU LESSER GENERAL PUBLIC LICENSE Version 3.
|
||||
You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html.
|
||||
You may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
package com.reliancy.dbo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Observable;
|
||||
|
||||
/**
|
||||
* Observable collection wrapper for monitoring data modifications.
|
||||
*
|
||||
* <p>A {@code Bag} is a {@link Collection} implementation that extends {@link Observable}
|
||||
* to notify observers of add/remove operations. It's designed as a holder for result sets
|
||||
* and provides a foundation for creating virtual collections backed by external data sources.
|
||||
*
|
||||
* <h2>Features:</h2>
|
||||
* <ul>
|
||||
* <li><b>Observable Pattern</b>: Fires {@link BagChanged} events on modifications</li>
|
||||
* <li><b>In-Memory Storage</b>: Backed by {@link ArrayList} by default</li>
|
||||
* <li><b>Extensible</b>: Can be subclassed for lazy-loading or database-backed collections</li>
|
||||
* <li><b>Standard Collection</b>: Implements full {@link Collection} interface</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Event Types:</h2>
|
||||
* <ul>
|
||||
* <li>{@link BagChanged#ADD} - element(s) added</li>
|
||||
* <li>{@link BagChanged#REMOVE} - element(s) removed</li>
|
||||
* <li>{@link BagChanged#ACCESS} - element accessed (for lazy loading)</li>
|
||||
* <li>{@link BagChanged#POST_LOAD} - after loading from external source</li>
|
||||
* <li>{@link BagChanged#PRE_SAVE} - before saving to external source</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Usage Example:</h2>
|
||||
* <pre>{@code
|
||||
* Bag<PersonDBO> people = new Bag<>();
|
||||
*
|
||||
* // Add observer
|
||||
* people.addObserver((observable, event) -> {
|
||||
* BagChanged<?> change = (BagChanged<?>) event;
|
||||
* switch (change.getOperation()) {
|
||||
* case BagChanged.ADD:
|
||||
* System.out.println("Added: " + Arrays.toString(change.getArguments()));
|
||||
* break;
|
||||
* case BagChanged.REMOVE:
|
||||
* System.out.println("Removed: " + Arrays.toString(change.getArguments()));
|
||||
* break;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Modifications trigger events
|
||||
* people.add(person1); // Observer notified
|
||||
* people.remove(person1); // Observer notified
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Fluent API:</h2>
|
||||
* <p>The {@link #append(Object)} method provides a chainable alternative to {@link #add(Object)}:
|
||||
* <pre>{@code
|
||||
* Bag<String> names = new Bag<>()
|
||||
* .append("Alice")
|
||||
* .append("Bob")
|
||||
* .append("Charlie");
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Construction:</h2>
|
||||
* <pre>{@code
|
||||
* // Empty bag
|
||||
* Bag<DBO> bag1 = new Bag<>();
|
||||
*
|
||||
* // From iterable
|
||||
* Bag<DBO> bag2 = new Bag<>(someList);
|
||||
*
|
||||
* // From iterator
|
||||
* Bag<DBO> bag3 = new Bag<>(resultIterator);
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Extension for Virtual Collections:</h2>
|
||||
* <p>Subclasses can override methods to implement lazy loading or database-backed storage:
|
||||
* <pre>{@code
|
||||
* public class LazyBag<E> extends Bag<E> {
|
||||
* @Override
|
||||
* public Iterator<E> iterator() {
|
||||
* notifyObservers(new BagChanged<>(this, BagChanged.ACCESS));
|
||||
* // Load from database on first access
|
||||
* return super.iterator();
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param <E> the type of elements in this bag
|
||||
* @see Observable
|
||||
* @see Collection
|
||||
* @see BagChanged
|
||||
*/
|
||||
public class Bag<E> extends Observable implements Collection<E>{
|
||||
/** event to send to observers. */
|
||||
public static final class BagChanged<E>{
|
||||
public static final int ADD=0;
|
||||
public static final int REMOVE=1;
|
||||
public static final int ACCESS=2;
|
||||
public static final int POST_LOAD=3;
|
||||
public static final int PRE_SAVE=4;
|
||||
final Bag<E> bag;
|
||||
final int operation;
|
||||
final Object[] arguments;
|
||||
|
||||
public BagChanged(Bag<E> p,int op,Object ... args){
|
||||
bag=p;
|
||||
operation=op;
|
||||
arguments=args;
|
||||
}
|
||||
public Bag<E> getBag() {
|
||||
return bag;
|
||||
}
|
||||
public int getOperation() {
|
||||
return operation;
|
||||
}
|
||||
public Object[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
final ArrayList<E> items=new ArrayList<>();
|
||||
|
||||
public Bag(){
|
||||
}
|
||||
public Bag(Iterable<E> o){
|
||||
this(o.iterator());
|
||||
}
|
||||
public Bag(Iterator<E> o){
|
||||
while(o.hasNext()) add(o.next());
|
||||
}
|
||||
@Override
|
||||
public int size() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size()==0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
final Iterator<E> it=iterator();
|
||||
while(it.hasNext()){
|
||||
final E e=it.next();
|
||||
if(e!=null && o!=null && e.equals(o)) return true;
|
||||
else if(e==o) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
for (Object e : c) if (!contains(e)) return false;
|
||||
return true;
|
||||
}
|
||||
public ListIterator<E> listIterator(){
|
||||
return listIterator(0);
|
||||
}
|
||||
public ListIterator<E> listIterator(int offset){
|
||||
return items.listIterator(offset);
|
||||
}
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return items.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return toArray(new Object[size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return items.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
if(items.contains(e)) return true;
|
||||
if(countObservers()>0){
|
||||
BagChanged<E> evt=new Bag.BagChanged<>(this,BagChanged.ADD,e);
|
||||
setChanged();
|
||||
notifyObservers(evt);
|
||||
}
|
||||
return items.add(e);
|
||||
}
|
||||
public Bag<E> append(E e){
|
||||
add(e);
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(!contains(o)) return false;
|
||||
if(countObservers()>0){
|
||||
BagChanged<E> evt=new Bag.BagChanged<>(this,BagChanged.REMOVE,o);
|
||||
setChanged();
|
||||
notifyObservers(evt);
|
||||
}
|
||||
return items.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
if(countObservers()>0){
|
||||
BagChanged<E> evt=new Bag.BagChanged<>(this,BagChanged.ADD,c.toArray());
|
||||
setChanged();
|
||||
notifyObservers(evt);
|
||||
}
|
||||
if(c==null || c.size()==0) return false;
|
||||
c.forEach(e->{this.append(e);});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
if(countObservers()>0){
|
||||
BagChanged<E> evt=new Bag.BagChanged<>(this,BagChanged.REMOVE,c!=null?c.toArray():null);
|
||||
setChanged();
|
||||
notifyObservers(evt);
|
||||
}
|
||||
if(c!=null){
|
||||
return items.removeAll(c);
|
||||
}else{
|
||||
items.clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return items.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
removeAll(null);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user