/*
* This file is part of aion-emu <aion-emu.com>.
*
* aion-emu is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aion-emu is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with aion-emu. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aionemu.gameserver.ai.desires;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.PriorityQueue;
/**
* This class represents desire queue, it's thread-safe. Desires can be added and removed. If desire is added - previous
* desires will be checked, if same desire found then desire previous one will be removed from the queue
*
* @author SoulKeeper
* @see com.aionemu.gameserver.ai.desires.Desire
* @see com.aionemu.gameserver.ai.desires.AbstractDesire
*/
public class DesireQueue
{
/**
* Prioritized Queue of desires, lazy initialization.
*/
protected PriorityQueue<Desire> queue;
/**
* Retuns first element of this queue not removing it. Returns null if there is no elements.
*
* @return first element or null
*/
public synchronized Desire peek()
{
return queue != null ? queue.peek() : null;
}
/**
* Removes first element from the desires list and removes it. Returns null if there are no elements.
*
* @return first element from the desires list or null.
*/
public synchronized Desire poll()
{
if(queue != null)
{
return queue.poll();
}
return null;
}
/**
* Adds desire to the queue.
* <p/>
* <p/>
* When adding object this method checks first for the same object by {@link AbstractDesire#equals(Object)}, if such
* object found, next actions will be done:<br>
* <br>
* 1). Remove old desire instance from the list.<br>
* 2). Check if those desires are same instances by "==".<br>
* 3). If they are not the same instances, add desire power from old instance to new instance, if they are - do
* nothing.<br>
* <br>
* After all add new desire instance to the list.
*
* @param desire
* desire instance to add
*/
public synchronized void addDesire(Desire desire)
{
// Lazy initialization of desire queue
if(queue == null)
{
queue = new PriorityQueue<Desire>();
}
// Iterate over the list to find similiar desires
Iterator<Desire> iterator = queue.iterator();
while(iterator.hasNext())
{
Desire iterated = iterator.next();
// Find similiar desires by #equals method, they can be different instances.
if(desire.equals(iterated))
{
// Remove the old desire from the list
iterator.remove();
// If current desire instance was not at the list - increase it's power
// by the value of another instance power
// and after that add it to the list
if(desire != iterated)
{
desire.increaseDesirePower(iterated.getDesirePower());
}
// Break iteration, desire list can't contain two same desires
break;
}
}
// finally add desire to the list
queue.add(desire);
}
/**
* Removes desire from this desireQueue. If desire was removed successfully this method return true, false
* otherwiese
*
* @param desire
* what desire to remove
* @return result of desire removal
*/
public synchronized boolean removeDesire(Desire desire)
{
return queue != null && queue.remove(desire);
}
/**
* Iterates over desires, you have to provide iteration handler and optionally filters.<br>
* <br>
* Handlers and filters can't call following methods:
* <ul>
* <li>{@link #addDesire(Desire)}</li>
* <li>{@link #poll()}</li>
* <li>{@link #removeDesire(Desire)}</li>
* </ul>
* <p/>
* However, method {@link #clear() can be called}.
*
* @param handler
* DesireIterationhandler that will be called on the iteration
* @param filters
* optional filters that will prevent passing unneede desires to the handler
* @throws java.util.ConcurrentModificationException
* only if called handler or filter modified this queue
* @see com.aionemu.gameserver.ai.desires.DesireIteratorFilter
* @see com.aionemu.gameserver.ai.desires.DesireIteratorFilter#isOk(Desire)
* @see com.aionemu.gameserver.ai.desires.DesireIteratorHandler
* @see com.aionemu.gameserver.ai.desires.DesireIteratorHandler#next(Desire , java.util.Iterator)
*/
public synchronized void iterateDesires(DesireIteratorHandler handler, DesireIteratorFilter... filters)
throws ConcurrentModificationException
{
if(queue == null)
{
return;
}
Iterator<Desire> iterator = queue.iterator();
outer: while(iterator.hasNext())
{
Desire desire = iterator.next();
if(filters != null && filters.length > 0)
{
for(DesireIteratorFilter filter : filters)
{
if(!filter.isOk(desire))
{
continue outer;
}
}
}
handler.next(desire, iterator);
}
}
/**
* Returns true if this desire list contains same desire. Desires are compared by
* {@link AbstractDesire#equals(Object)} method.
*
* @param desire
* what desire to search
* @return true if there is equal desire, false in other case.
*/
public synchronized boolean contains(Desire desire)
{
return queue.contains(desire);
}
/**
* Returns true if this npc has no any desires added
*
* @return true if this npc has no any desires added
*/
public synchronized boolean isEmpty()
{
return queue == null || queue.isEmpty();
}
/**
* Clears all desires
*/
public synchronized void clear()
{
if(queue != null)
{
Desire desire = null;
while((desire = queue.poll()) != null)
desire.onClear();
}
}
/**
* Returns size of the desire list
*
* @return size of remaining desires
*/
public synchronized int size()
{
return queue == null ? 0 : queue.size();
}
}