1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-11 09:42:54 +00:00

Change-Id: I0cca627373c68d94025647f802a7fa6b419e0aad

This commit is contained in:
rogiel
2011-04-30 01:51:36 -03:00
parent f1d8e6588f
commit f454e3c35a
74 changed files with 2744 additions and 255 deletions

View File

@@ -1,5 +1,24 @@
package com.l2jserver.model.id;
public interface CharacterID extends ObjectID {
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.db.dao.CharacterDAO;
import com.l2jserver.model.world.L2Character;
public final class CharacterID extends ObjectID<L2Character> {
/**
* Data Access Object (DAO) for characters
*/
private final CharacterDAO characterDao;
@Inject
public CharacterID(@Assisted int id, CharacterDAO characterDao) {
super(id);
this.characterDao = characterDao;
}
@Override
public L2Character getObject() {
return characterDao.load(this);
}
}

View File

@@ -0,0 +1,23 @@
package com.l2jserver.model.id;
import com.google.inject.Inject;
import com.l2jserver.db.dao.ClanDAO;
import com.l2jserver.model.world.Clan;
public final class ClanID extends ObjectID<Clan> {
/**
* Data Access Object (DAO) for clans
*/
private final ClanDAO clanDao;
@Inject
protected ClanID(int id, ClanDAO clanDao) {
super(id);
this.clanDao = clanDao;
}
@Override
public Clan getObject() {
return clanDao.load(this);
}
}

View File

@@ -1,5 +1,55 @@
package com.l2jserver.model.id;
public interface ID {
import com.google.inject.Inject;
/**
* The ID interface. Each Object or Template must be represented by an unique
* ID.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public abstract class ID {
/**
* The id itself
*/
protected final int id;
@Inject
protected ID(int id) {
this.id = id;
}
/**
* @return the id
*/
public int getID() {
return id;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + " [id=" + id + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ID other = (ID) obj;
if (id != other.id)
return false;
return true;
}
}

View File

@@ -0,0 +1,24 @@
package com.l2jserver.model.id;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.db.dao.ItemDAO;
import com.l2jserver.model.world.Item;
public final class ItemID extends ObjectID<Item> {
/**
* Data Access Object (DAO) for items
*/
private final ItemDAO itemDao;
@Inject
protected ItemID(@Assisted int id, ItemDAO itemDao) {
super(id);
this.itemDao = itemDao;
}
@Override
public Item getObject() {
return itemDao.load(this);
}
}

View File

@@ -1,5 +1,23 @@
package com.l2jserver.model.id;
public interface ObjectID extends ID {
import com.l2jserver.model.id.factory.IDFactory;
import com.l2jserver.model.world.WorldObject;
/**
* {@link ObjectID}s cannot be instantiated directly. This must be done through
* an {@link IDFactory}. The {@link ObjectID} provides a facility
* {@link #getObject() method} that allows easily fetch this object from
* database without the need to directly use DAOs.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <T>
* the {@link WorldObject} type
*/
public abstract class ObjectID<T extends WorldObject> extends ID {
protected ObjectID(int id) {
super(id);
}
public abstract T getObject();
}

View File

@@ -0,0 +1,23 @@
package com.l2jserver.model.id;
import com.google.inject.Inject;
import com.l2jserver.db.dao.PetDAO;
import com.l2jserver.model.world.Pet;
public final class PetID extends ObjectID<Pet> {
/**
* Data Access Object (DAO) for pets
*/
private final PetDAO petDao;
@Inject
protected PetID(int id, PetDAO petDao) {
super(id);
this.petDao = petDao;
}
@Override
public Pet getObject() {
return petDao.load(this);
}
}

View File

@@ -1,5 +0,0 @@
package com.l2jserver.model.id;
public class SimpleID implements ID {
}

View File

@@ -1,5 +1,14 @@
package com.l2jserver.model.id;
public interface TemplateID extends ID {
/**
* Templates IDs, different from {@link ObjectID}s, can be repeated and are
* defined in the template class.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public final class TemplateID extends ID {
public TemplateID(int id) {
super(id);
}
}

View File

@@ -0,0 +1,114 @@
package com.l2jserver.model.id.allocator;
import java.util.BitSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.l2jserver.util.PrimeFinder;
public class BitSetIDAllocator implements IDAllocator {
/**
* Lock to guarantee synchronization
*/
private Lock lock = new ReentrantLock();
/**
* Available IDs
*/
private BitSet ids = new BitSet();
/**
* Amount of free ids
*/
private AtomicInteger freeIdCount = new AtomicInteger();
/**
* Next free ID
*/
private AtomicInteger nextId = new AtomicInteger();
public void init() {
ids = new BitSet(PrimeFinder.nextPrime(100000));
ids.clear();
freeIdCount = new AtomicInteger(ALLOCABLE_IDS);
nextId = new AtomicInteger(ids.nextClearBit(0));
}
@Override
public void allocate(int id) {
if (ids.get(id - FIRST_ID))
throw new IDAllocatorException("ID not allocated");
lock.lock();
try {
if (id < FIRST_ID)
return;
ids.set(id - FIRST_ID);
nextId = new AtomicInteger(ids.nextClearBit(0));
} finally {
lock.unlock();
}
}
@Override
public int allocate() {
lock.lock();
try {
final int newID = nextId.get();
ids.set(newID);
freeIdCount.decrementAndGet();
int nextFree = ids.nextClearBit(newID);
if (nextFree < 0) {
nextFree = ids.nextClearBit(0);
}
if (nextFree < 0) {
if (ids.size() < ALLOCABLE_IDS) {
increaseBitSetCapacity();
} else {
throw new IDAllocatorException("ID exhaustion");
}
}
nextId.set(nextFree);
return newID + FIRST_ID;
} finally {
lock.unlock();
}
}
@Override
public void release(int id) {
if (id < FIRST_ID)
throw new IDAllocatorException(
"Can't release ID, smaller then initial ID");
if (!ids.get(id - FIRST_ID))
throw new IDAllocatorException("ID not allocated");
lock.lock();
try {
ids.clear(id - FIRST_ID);
freeIdCount.incrementAndGet();
} finally {
lock.unlock();
}
}
private void increaseBitSetCapacity() {
BitSet newBitSet = new BitSet(
PrimeFinder.nextPrime((getAllocatedIDs() * 11) / 10));
newBitSet.or(ids);
ids = newBitSet;
}
@Override
public int getAllocatedIDs() {
return ALLOCABLE_IDS - getFreeIDs();
}
@Override
public int getFreeIDs() {
return freeIdCount.get();
}
}

View File

@@ -0,0 +1,59 @@
package com.l2jserver.model.id.allocator;
/**
* The ID allocator is used to alloc new ID and to release IDs that aren't used
* anymore.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface IDAllocator {
/**
* The first ID ever allocated
*/
public final static int FIRST_ID = 0x10000000;
/**
* The last ID ever allocated
*/
public final static int LAST_ID = 0x7FFFFFFF;
/**
* Total of available IDs for allocation
*/
public final static int ALLOCABLE_IDS = LAST_ID - FIRST_ID;
/**
* This is method is used to register IDs as used at startup time.
*
* @param id
* the id
*/
void allocate(int id);
/**
* Allocates a new ID
*
* @return the allocated ID value
*/
int allocate();
/**
* Release an ID
*
* @param id
* the id
*/
void release(int id);
/**
* Get the amount of already allocated IDs
*
* @return allocated ids count
*/
int getAllocatedIDs();
/**
* Get the amount of IDs remaining to be allocated
*
* @return free ids count
*/
int getFreeIDs();
}

View File

@@ -0,0 +1,21 @@
package com.l2jserver.model.id.allocator;
public class IDAllocatorException extends RuntimeException {
private static final long serialVersionUID = 111195059766878062L;
public IDAllocatorException() {
super();
}
public IDAllocatorException(String message, Throwable cause) {
super(message, cause);
}
public IDAllocatorException(String message) {
super(message);
}
public IDAllocatorException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,62 @@
package com.l2jserver.model.id.factory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.CharacterID;
import com.l2jserver.model.id.allocator.IDAllocator;
/**
* {@link IDFactory} for {@link CharacterID}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class CharacterIDFactory implements ObjectIDFactory<CharacterID> {
/**
* The ID allocator
*/
private final IDAllocator allocator;
/**
* The Guice Factory
*/
private final CharacterIDGuiceFactory factory;
@Inject
public CharacterIDFactory(IDAllocator allocator,
CharacterIDGuiceFactory factory) {
super();
this.allocator = allocator;
this.factory = factory;
}
@Override
public CharacterID createID() {
return createID(allocator.allocate());
}
@Override
public CharacterID createID(int id) {
return factory.create(id);
}
@Override
public void destroy(CharacterID id) {
allocator.release(id.getID());
}
/**
* This is an Google Guice factory. Assistect Inject extension will
* automatically implement it and create the injected instances.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface CharacterIDGuiceFactory {
/**
* Creates a new ID instance
*
* @param id
* the numeric ID
* @return the new ID created by injection
*/
public CharacterID create(@Assisted int id);
}
}

View File

@@ -0,0 +1,61 @@
package com.l2jserver.model.id.factory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.ClanID;
import com.l2jserver.model.id.allocator.IDAllocator;
/**
* {@link IDFactory} for {@link ClanID}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class ClanIDFactory implements ObjectIDFactory<ClanID> {
/**
* The ID allocator
*/
private final IDAllocator allocator;
/**
* The Guice factory
*/
private final ClanIDGuiceFactory factory;
@Inject
public ClanIDFactory(IDAllocator allocator, ClanIDGuiceFactory factory) {
super();
this.allocator = allocator;
this.factory = factory;
}
@Override
public ClanID createID() {
return createID(allocator.allocate());
}
@Override
public ClanID createID(int id) {
return factory.create(id);
}
@Override
public void destroy(ClanID id) {
allocator.release(id.getID());
}
/**
* This is an Google Guice factory. Assistect Inject extension will
* automatically implement it and create the injected instances.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface ClanIDGuiceFactory {
/**
* Creates a new ID instance
*
* @param id
* the numeric ID
* @return the new ID created by injection
*/
public ClanID create(@Assisted int id);
}
}

View File

@@ -0,0 +1,34 @@
package com.l2jserver.model.id.factory;
import com.l2jserver.model.id.ID;
/**
* The ID factory is used to create instances of IDs. It will automatically make
* sure the ID is free before allocating it.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface IDFactory<T extends ID> {
/**
* Generated a new ID
*
* @return the new ID
*/
T createID();
/**
* Creates the ID object for an <b>EXISTING</b> ID.
*
* @param id
* @return
*/
T createID(int id);
/**
* Destroy this ID. Releases this value to be used once again.
*
* @param id
* the id to be destroyed.
*/
void destroy(T id);
}

View File

@@ -0,0 +1,29 @@
package com.l2jserver.model.id.factory;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.l2jserver.model.id.allocator.BitSetIDAllocator;
import com.l2jserver.model.id.allocator.IDAllocator;
import com.l2jserver.model.id.factory.CharacterIDFactory.CharacterIDGuiceFactory;
import com.l2jserver.model.id.factory.ItemIDFactory.ItemIDGuiceFactory;
public class IDFactoryModule extends AbstractModule {
@Override
protected void configure() {
bind(IDAllocator.class).to(BitSetIDAllocator.class)
.in(Scopes.SINGLETON);
bind(CharacterIDFactory.class).in(Scopes.SINGLETON);
install(new FactoryModuleBuilder().build(CharacterIDGuiceFactory.class));
bind(ItemIDFactory.class).in(Scopes.SINGLETON);
install(new FactoryModuleBuilder().build(ItemIDGuiceFactory.class));
// bind(ClanIDFactory.class).in(Scopes.SINGLETON);
// install(new FactoryModuleBuilder().build(ClanIDGuiceFactory.class));
//
// bind(PetIDFactory.class).in(Scopes.SINGLETON);
// install(new FactoryModuleBuilder().build(PetIDGuiceFactory.class));
}
}

View File

@@ -0,0 +1,61 @@
package com.l2jserver.model.id.factory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.ItemID;
import com.l2jserver.model.id.allocator.IDAllocator;
/**
* {@link IDFactory} for {@link ItemID}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class ItemIDFactory implements ObjectIDFactory<ItemID> {
/**
* The ID allocator
*/
private final IDAllocator allocator;
/**
* The Guice factory
*/
private final ItemIDGuiceFactory factory;
@Inject
public ItemIDFactory(IDAllocator allocator, ItemIDGuiceFactory factory) {
super();
this.allocator = allocator;
this.factory = factory;
}
@Override
public ItemID createID() {
return createID(allocator.allocate());
}
@Override
public ItemID createID(int id) {
return factory.create(id);
}
@Override
public void destroy(ItemID id) {
allocator.release(id.getID());
}
/**
* This is an Google Guice factory. Assistect Inject extension will
* automatically implement it and create the injected instances.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface ItemIDGuiceFactory {
/**
* Creates a new ID instance
*
* @param id
* the numeric ID
* @return the new ID created by injection
*/
public ItemID create(@Assisted int id);
}
}

View File

@@ -0,0 +1,6 @@
package com.l2jserver.model.id.factory;
import com.l2jserver.model.id.ObjectID;
public interface ObjectIDFactory<T extends ObjectID<?>> extends IDFactory<T> {
}

View File

@@ -0,0 +1,61 @@
package com.l2jserver.model.id.factory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.l2jserver.model.id.PetID;
import com.l2jserver.model.id.allocator.IDAllocator;
/**
* {@link IDFactory} for {@link PetID}.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class PetIDFactory implements ObjectIDFactory<PetID> {
/**
* The ID allocator
*/
private final IDAllocator allocator;
/**
* The Guice factory
*/
private final PetIDGuiceFactory factory;
@Inject
public PetIDFactory(IDAllocator allocator, PetIDGuiceFactory factory) {
super();
this.allocator = allocator;
this.factory = factory;
}
@Override
public PetID createID() {
return createID(allocator.allocate());
}
@Override
public PetID createID(int id) {
return factory.create(id);
}
@Override
public void destroy(PetID id) {
allocator.release(id.getID());
}
/**
* This is an Google Guice factory. Assistect Inject extension will
* automatically implement it and create the injected instances.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface PetIDGuiceFactory {
/**
* Creates a new ID instance
*
* @param id
* the numeric ID
* @return the new ID created by injection
*/
public PetID create(@Assisted int id);
}
}