/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* Licensed 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.utils.reply;
import java.lang.ref.WeakReference;
import loon.utils.reply.Bypass.GoListener;
class Cons extends Connection
{
private Bypass _owner;
private ListenerRef _ref;
private boolean _oneShot;
private int _priority;
public Cons next;
public final boolean oneShot () { return _oneShot; }
public GoListener listener () {
return _ref.get(this);
}
@Override public void close () {
if (_owner != null) {
_ref.defang(_owner.placeholderListener());
_owner.disconnect(this);
_owner = null;
}
}
@Override public Connection once () {
_oneShot = true;
return this;
}
@Override public Connection setPriority (int priority) {
if (_owner == null){ throw new IllegalStateException(
"Cannot change priority of disconnected connection.");
}
_owner.disconnect(this);
next = null;
_priority = priority;
_owner.addCons(this);
return this;
}
@Override public Connection holdWeakly () {
if (_owner == null){ throw new IllegalStateException(
"Cannot change disconnected connection to weak.");
}
if (!_ref.isWeak()) {
_ref = new WeakRef(_ref.get(this));
}
return this;
}
@Override public String toString () {
return "[owner=" + _owner + ", pri=" + _priority + ", lner=" + listener() +
", hasNext=" + (next != null) + ", oneShot=" + oneShot() + "]";
}
protected Cons (Bypass owner, GoListener listener) {
_owner = owner;
_ref = new StrongRef(listener);
}
private static abstract class ListenerRef {
abstract boolean isWeak ();
abstract void defang (GoListener def);
abstract GoListener get (Cons cons);
}
private static class StrongRef extends ListenerRef {
private GoListener _lner;
public StrongRef (GoListener lner) { _lner = lner; }
public boolean isWeak () { return false; }
public void defang (GoListener def) { _lner = def; }
public GoListener get (Cons cons) { return _lner; }
}
private static class WeakRef extends ListenerRef {
private WeakReference<GoListener> _wref;
private GoListener _def;
public WeakRef (GoListener lner) { _wref = new WeakReference<GoListener>(lner); }
public boolean isWeak () { return true; }
public void defang (GoListener def) { _def = def; _wref = null; }
public GoListener get (Cons cons) {
if (_wref != null) {
GoListener listener = _wref.get();
if (listener != null){
return listener;
}
cons.close();
}
return _def;
}
}
static Cons insert (Cons head, Cons cons) {
if (head == null) {
return cons;
} else if (cons._priority > head._priority) {
cons.next = head;
return cons;
} else {
head.next = insert(head.next, cons);
return head;
}
}
static Cons remove (Cons head, Cons cons) {
if (head == null) {
return head;
}
if (head == cons) {
return head.next;
}
head.next = remove(head.next, cons);
return head;
}
static Cons removeAll (Cons head, GoListener listener) {
if (head == null) {
return null;
}
if (head.listener() == listener) {
return removeAll(head.next, listener);
}
head.next = removeAll(head.next, listener);
return head;
}
}