0001: /*
0002: * Copyright (c) 2001 Silvere Martin-Michiellot All Rights Reserved.
0003: *
0004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
0005: * royalty free, license to use, modify and redistribute this
0006: * software in source and binary code form,
0007: * provided that i) this copyright notice and license appear on all copies of
0008: * the software; and ii) Licensee does not utilize the software in a manner
0009: * which is disparaging to Silvere Martin-Michiellot.
0010: *
0011: * This software is provided "AS IS," without a warranty of any kind. ALL
0012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
0013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
0014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
0015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
0016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
0017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
0018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
0019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
0020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
0021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
0022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
0023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
0024: *
0025: * This software is not designed or intended for use in on-line control of
0026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
0027: * the design, construction, operation or maintenance of any nuclear
0028: * facility. Licensee represents and warrants that it will not use or
0029: * redistribute the Software for such purposes.
0030: *
0031: * @Author: Silvere Martin-Michiellot
0032: *
0033: */
0034:
0035: package com.db.server;
0036:
0037: import javax.jdo.*;
0038: import java.util.*;
0039: import javax.media.j3d.*;
0040: import javax.vecmath.*;
0041: import java.security.PublicKey;
0042: import java.lang.reflect.*;
0043:
0044: /**
0045: */
0046:
0047: public class WorldSpot extends Object {
0048:
0049: /**
0050: * Position and orientation of the "center" of the World Spot relatively to the universe coordinate system
0051: * encompass (the bounding volume covered by the World Spot around its origin)
0052: * ruler (pointer to the administrator who has full rights on the World Spot) (this field should use a public key to uniquely
0053: * identify the ruler accross the Internet)
0054: * informations:
0055: * Date
0056: * Creator author Name, E-mail, Public Key
0057: * Given name for World Spot
0058: * Version
0059: * libraries:
0060: * objects
0061: * tools
0062: * guides
0063: * avatar skins
0064: * backgrounds
0065: * use from the static library instanciated objects or imported objects or user created objects (not in the library)
0066: * objects
0067: * (maps) soil
0068: * (maps) buildings
0069: * (maps) plants
0070: * (meteo: sun stars sky) visual background
0071: * (meteo) sound background
0072: * tools (in world or inventory of users)
0073: * guides (in world or inventory of users)
0074: * avatar (carries user information and is always instancited and potentially active to receive information from guides for example even if no client is connected)
0075: * lands
0076: * feudal relation between users
0077: * client information (and it's pointer to the avatar)
0078: **/
0079:
0080: public final static String STRING_DATE = "Date";
0081: public final static String STRING_CREATOR_NAME = "Creator Name";
0082: public final static String STRING_CREATOR_E_MAIL = "Creator e-mail";
0083: public final static String STRING_CREATOR_PUBLIC_KEY = "Creator Public Key";
0084: public final static String STRING_NAME = "Name";
0085: public final static String STRING_VERSION = "Version";
0086:
0087: private UniverseServer universeServer;
0088: private Avatar ruler;
0089: private Hashtable information;
0090: private HashSet pools;
0091: private Trade trade;
0092:
0093: //worldSpotLibrary includes libraries of objects, tools and guides
0094: //worldSpotLibrary includes in-world objects, tools and guides
0095: //some avatars may actually be disconnected and get no Information from client
0096:
0097: private WorldSpot() {
0098:
0099: throw new java.lang.IllegalArgumentException(
0100: "A world spot must have at least a universeServer and a ruler.");
0101:
0102: }
0103:
0104: public WorldSpot(UniverseServer universeServer, Avatar ruler) {
0105:
0106: this (universeServer, ruler, new BoundingSphere(new Point3d(0,
0107: 0, 0), Double.MAX_VALUE));
0108:
0109: }
0110:
0111: //upon worldSpot creation, ruler is allocated full land of the worldSpot
0112: //worldSpot addition should be done via the universeServer
0113: public WorldSpot(UniverseServer universeServer, Avatar ruler,
0114: Bounds bounds) {
0115:
0116: Transaction transaction;
0117: Land land;
0118: Vector currenciesIdentifiers;
0119: double[][] currencies;
0120:
0121: if ((universeServer != null) && (ruler != null)
0122: && (bounds != null) && (!bounds.isEmpty())) {
0123:
0124: this .universeServer = universeServer;
0125: this .ruler = ruler;
0126:
0127: land = new Land(this .getUniverseServer(), this .ruler,
0128: bounds);
0129:
0130: //add land to database
0131: try {
0132: transaction = this .getPersistenceManager()
0133: .currentTransaction();
0134: transaction.begin();
0135:
0136: this .getPersistenceManager().makePersistent(land);
0137:
0138: transaction.commit();
0139: } catch (Exception exception) {
0140: }
0141:
0142: currenciesIdentifiers = new Vector();
0143: currenciesIdentifiers.add(Trade.US_DOLLAR);
0144: currencies = new double[1][1];
0145: currencies[0][0] = 1;
0146:
0147: this .trade = new Trade(this .getUniverseServer(),
0148: currenciesIdentifiers, currencies);
0149:
0150: } else {
0151: throw new java.lang.IllegalArgumentException(
0152: "A world spot must have a valid universeServer, a valid ruler and valid bounds.");
0153: }
0154:
0155: }
0156:
0157: public final UniverseServer getUniverseServer() {
0158:
0159: return this .universeServer;
0160:
0161: }
0162:
0163: private final PersistenceManager getPersistenceManager() {
0164:
0165: return this .universeServer.getPersistenceManager();
0166:
0167: }
0168:
0169: //notifies changes to server
0170: //Bounds correspond to Land union not to BackgroundWorld's bounds
0171: public final Bounds getBounds() {
0172:
0173: Transaction transaction;
0174: Extent extent;
0175: Query query;
0176: String filter;
0177: Collection collection;
0178: BoundingPolytope currentBounds;
0179: Land land;
0180: Iterator iterator;
0181:
0182: try {
0183: transaction = this .getPersistenceManager()
0184: .currentTransaction();
0185: transaction.begin();
0186:
0187: extent = this .getPersistenceManager().getExtent(Land.class,
0188: true);
0189: filter = new String("SELECT * FROM Land");
0190: query = this .getPersistenceManager().newQuery(Land.class,
0191: extent, filter);
0192: collection = (Collection) query.execute();
0193:
0194: transaction.commit();
0195:
0196: currentBounds = new BoundingPolytope();
0197: iterator = collection.iterator();
0198:
0199: while (iterator.hasNext()) {
0200: land = (Land) iterator.next();
0201: currentBounds.combine(land.getBounds());
0202: }
0203:
0204: universeServer.notifyBoundsChange(this );
0205:
0206: return currentBounds;
0207:
0208: } catch (Exception exception) {
0209:
0210: return null;
0211:
0212: }
0213:
0214: }
0215:
0216: //ruler only call
0217: //bounds should be at least big enough to encompass all current lands and if not
0218: //bounds will be set nevertheless to fit the union of land bounds.
0219: public final void setBounds(Bounds bounds) {
0220:
0221: Transaction transaction;
0222: Extent extent;
0223: Query query;
0224: String filter;
0225: Collection collection;
0226: ExtendedBoundingPolytope currentBounds;
0227: ExtendedBoundingPolytope newBounds;
0228: Land land;
0229:
0230: try {
0231: transaction = this .getPersistenceManager()
0232: .currentTransaction();
0233: transaction.begin();
0234:
0235: extent = this .getPersistenceManager().getExtent(Land.class,
0236: true);
0237: filter = new String("SELECT * FROM Land");
0238: query = this .getPersistenceManager().newQuery(Land.class,
0239: extent, filter);
0240: collection = (Collection) query.execute();
0241:
0242: transaction.commit();
0243:
0244: currentBounds = new ExtendedBoundingPolytope();
0245: currentBounds.combine((Bounds[]) collection.toArray());
0246:
0247: newBounds = new ExtendedBoundingPolytope(bounds);
0248:
0249: if (newBounds.contains(currentBounds)) {
0250:
0251: land = new Land(this .getUniverseServer(), this .ruler,
0252: newBounds.subtract(currentBounds));
0253:
0254: //add land to database
0255: try {
0256: transaction = this .getPersistenceManager()
0257: .currentTransaction();
0258: transaction.begin();
0259:
0260: this .getPersistenceManager().makePersistent(land);
0261:
0262: transaction.commit();
0263: } catch (Exception exception) {
0264: }
0265:
0266: }
0267:
0268: } catch (Exception exception) {
0269: }
0270:
0271: }
0272:
0273: public final Trade getTrade() {
0274:
0275: return this .trade;
0276:
0277: }
0278:
0279: //can only be called by ruler
0280: //there is always one and only one active trade for all the pools in the worldspot
0281: //think about users when changing a trade which should never happen or only to add new currency values
0282: //but PLEASE keep old currencies avaiable because secured V-Cash wallet wont be able to update their money currency by themselves
0283: public final void setTrade(Trade trade) {
0284:
0285: Iterator iterator;
0286: Pool currentPool;
0287:
0288: if (trade != null) {
0289: iterator = this .pools.iterator();
0290:
0291: while (iterator.hasNext()) {
0292: currentPool = (Pool) iterator.next();
0293: currentPool.setTrade(trade);
0294: }
0295:
0296: this .trade = trade;
0297:
0298: }
0299:
0300: }
0301:
0302: public final HashSet getPools() {
0303:
0304: this .clearEmptyPools();
0305:
0306: return this .pools;
0307:
0308: }
0309:
0310: //should be connected to a ToolWorld (pool access and contents)
0311: public final Pool startPool(Avatar avatar) {
0312:
0313: Pool pool;
0314:
0315: this .clearEmptyPools();
0316:
0317: pool = new Pool(this .getUniverseServer(), avatar, this .trade);
0318: this .pools.add(pool);
0319:
0320: return pool;
0321:
0322: }
0323:
0324: private final void clearEmptyPools() {
0325:
0326: Iterator iterator;
0327: HashSet hashSet;
0328: Pool currentPool;
0329:
0330: synchronized (this .pools) {
0331:
0332: iterator = this .pools.iterator();
0333:
0334: //clear empty pools
0335: hashSet = new HashSet();
0336: while (iterator.hasNext()) {
0337: currentPool = (Pool) iterator.next();
0338: if (currentPool.checkPool()) {
0339: hashSet.add(currentPool);
0340: }
0341: }
0342:
0343: this .pools = hashSet;
0344: }
0345:
0346: }
0347:
0348: //Pools can be broken by a common lord (avatar) of all current users
0349: //this user doesn't need to be added to the avatarPool to delete it (as a superuser)
0350: //all current offers are completed before the avatarPool is deleted and remaining objects "transfered back" to their owners
0351: //it is not possible to delete a pool in which a pawn user has put some objects
0352: //(just to prevent there is no orphan objects)
0353: public final void closePool(Pool pool, Avatar avatar) {
0354:
0355: int feudalRelation;
0356:
0357: if (this .pools.contains(pool)) {
0358:
0359: synchronized (avatar) {
0360:
0361: pool.updatePool();
0362:
0363: if (pool.closablePool()) {
0364:
0365: feudalRelation = Avatar.getFeudalRelation(avatar,
0366: avatar.getCommonLord(pool.avatarsInPool()));
0367: if ((feudalRelation == Avatar.SELF)
0368: || (feudalRelation == Avatar.LORD)) {
0369:
0370: this .pools.remove(pool);
0371: pool = null;
0372:
0373: }
0374:
0375: }
0376:
0377: }
0378:
0379: }
0380:
0381: }
0382:
0383: protected final Avatar getRuler() {
0384:
0385: return this .ruler;
0386:
0387: }
0388:
0389: //XXXXX check call is valid
0390: public final void setRuler(Avatar ruler) {
0391:
0392: this .ruler = ruler;
0393: Avatar.moveUserInHierarchy(ruler, null);
0394:
0395: }
0396:
0397: public final Hashtable getInformation() {
0398:
0399: information.put(WorldSpot.STRING_DATE, this .getDate());
0400: information.put(WorldSpot.STRING_CREATOR_NAME, this
0401: .getCreatorName());
0402: information.put(WorldSpot.STRING_CREATOR_E_MAIL, this
0403: .getCreatorEMail());
0404: information.put(WorldSpot.STRING_CREATOR_PUBLIC_KEY, this
0405: .getCreatorPublicKey());
0406: information.put(WorldSpot.STRING_NAME, this .getName());
0407: information.put(WorldSpot.STRING_VERSION, this .getVersion());
0408:
0409: return information;
0410:
0411: }
0412:
0413: public final Object getInformation(String key) {
0414:
0415: information.put(WorldSpot.STRING_DATE, this .getDate());
0416: information.put(WorldSpot.STRING_CREATOR_NAME, this
0417: .getCreatorName());
0418: information.put(WorldSpot.STRING_CREATOR_E_MAIL, this
0419: .getCreatorEMail());
0420: information.put(WorldSpot.STRING_CREATOR_PUBLIC_KEY, this
0421: .getCreatorPublicKey());
0422: information.put(WorldSpot.STRING_NAME, this .getName());
0423: information.put(WorldSpot.STRING_VERSION, this .getVersion());
0424:
0425: return information.get(key);
0426:
0427: }
0428:
0429: public final Date getDate() {
0430:
0431: return (Date) this .getInformation(WorldSpot.STRING_DATE);
0432:
0433: }
0434:
0435: public final String getCreatorName() {
0436:
0437: return (String) this
0438: .getInformation(WorldSpot.STRING_CREATOR_NAME);
0439:
0440: }
0441:
0442: public final String getCreatorEMail() {
0443:
0444: return (String) this
0445: .getInformation(WorldSpot.STRING_CREATOR_E_MAIL);
0446:
0447: }
0448:
0449: public final PublicKey getCreatorPublicKey() {
0450:
0451: return (PublicKey) this
0452: .getInformation(WorldSpot.STRING_CREATOR_PUBLIC_KEY);
0453:
0454: }
0455:
0456: public final String getName() {
0457:
0458: return (String) this .getInformation(WorldSpot.STRING_NAME);
0459:
0460: }
0461:
0462: public final String getVersion() {
0463:
0464: return (String) this .getInformation(WorldSpot.STRING_VERSION);
0465:
0466: }
0467:
0468: //can only be called by ruler
0469: public final void setDate(Date date) {
0470:
0471: this .addInformation(WorldSpot.STRING_DATE, date.toString());
0472:
0473: }
0474:
0475: //can only be called by ruler
0476: public final void setCreatorName(String name) {
0477:
0478: this .addInformation(WorldSpot.STRING_CREATOR_NAME, name);
0479:
0480: }
0481:
0482: //can only be called by ruler
0483: public final void setCreatorEMail(String eMail) {
0484:
0485: this .addInformation(WorldSpot.STRING_CREATOR_E_MAIL, eMail);
0486:
0487: }
0488:
0489: //can only be called by ruler
0490: public final void setCreatorPublicKey(PublicKey publicKey) {
0491:
0492: this .addInformation(WorldSpot.STRING_CREATOR_PUBLIC_KEY,
0493: publicKey.toString());
0494:
0495: }
0496:
0497: //can only be called by ruler
0498: //rulers should avoid setting the name after creation of world spot as it is used by the clients to now where they are connected
0499: public final void setName(String name) {
0500:
0501: this .addInformation(WorldSpot.STRING_NAME, name);
0502:
0503: }
0504:
0505: //can only be called by ruler
0506: public final void setVersion(String version) {
0507:
0508: this .addInformation(WorldSpot.STRING_VERSION, version);
0509:
0510: }
0511:
0512: //obliterates every previously stored information including reserved fields
0513: public final void setInformation(Hashtable information) {
0514:
0515: this .information = information;
0516:
0517: }
0518:
0519: //can only be called by ruler
0520: //use the corresponding method to set the individual default fields
0521: public final void addInformation(String key, String keyValue) {
0522:
0523: //check if it is a reserved field or not
0524: if ((key != WorldSpot.STRING_DATE)
0525: && (key != WorldSpot.STRING_CREATOR_NAME)
0526: && (key != WorldSpot.STRING_CREATOR_E_MAIL)
0527: && (key != WorldSpot.STRING_CREATOR_PUBLIC_KEY)
0528: && (key != WorldSpot.STRING_NAME)
0529: && (key != WorldSpot.STRING_VERSION)) {
0530: this .information.put(key, keyValue);
0531: } else {
0532: throw new IllegalArgumentException(
0533: "You can't add directely Information on the restricted fields.");
0534: }
0535:
0536: }
0537:
0538: //can only be called by ruler
0539: public final void removeInformation(String key) {
0540:
0541: //check if it is a reserved field or not
0542: if ((key != WorldSpot.STRING_DATE)
0543: && (key != WorldSpot.STRING_CREATOR_NAME)
0544: && (key != WorldSpot.STRING_CREATOR_E_MAIL)
0545: && (key != WorldSpot.STRING_CREATOR_PUBLIC_KEY)
0546: && (key != WorldSpot.STRING_NAME)
0547: && (key != WorldSpot.STRING_VERSION)) {
0548: this .information.remove(key);
0549: } else {
0550: throw new IllegalArgumentException(
0551: "You can't remove directely Information on the restricted fields.");
0552: }
0553:
0554: }
0555:
0556: //please use this method only for ObjectWorlds, not for Skins, BackgroundWorlds, Lands
0557: public final void addObjectWorldToLibrary(Class objectWorld) {
0558:
0559: int modifiers;
0560: Constructor[] constructors;
0561: Modifier modifier;
0562: Class[] classes;
0563: Transaction transaction;
0564:
0565: modifiers = objectWorld.getModifiers();
0566: modifier = new Modifier();
0567: if (objectWorld.isAssignableFrom(ObjectWorld.class)) {
0568: if (!(modifier.isAbstract(modifiers))
0569: && !(modifier.isPrivate(modifiers))
0570: && !(modifier.isInterface(modifiers))) {
0571: constructors = objectWorld.getDeclaredConstructors();
0572: if (constructors.length > 0) {
0573: classes = constructors[0].getParameterTypes();
0574: if ((classes[0]
0575: .equals("[Lcom.db.server.UniverseServer"))
0576: && (classes[1]
0577: .equals("[Lcom.db.world.Avatar"))) {
0578: //add if not already added
0579: try {
0580: transaction = this .getPersistenceManager()
0581: .currentTransaction();
0582: transaction.begin();
0583:
0584: this .getPersistenceManager()
0585: .makePersistent(objectWorld);
0586:
0587: transaction.commit();
0588: } catch (Exception exception) {
0589: }
0590:
0591: this .notifyFilterers(Filter.ADDITION,
0592: objectWorld);
0593:
0594: }
0595: }
0596: }
0597: }
0598:
0599: }
0600:
0601: public final void removeObjectWorldFromLibrary(Class objectWorld) {
0602:
0603: //remove if exists
0604:
0605: Transaction transaction;
0606:
0607: try {
0608: transaction = this .getPersistenceManager()
0609: .currentTransaction();
0610: transaction.begin();
0611:
0612: this .getPersistenceManager().deletePersistent(objectWorld);
0613:
0614: transaction.commit();
0615: } catch (Exception exception) {
0616: }
0617:
0618: this .notifyFilterers(Filter.DELETION, objectWorld);
0619:
0620: }
0621:
0622: //price of the instanciated object should be 0
0623: //owner then sets up the price he wants to sell its objectWorld if he really wants to sell
0624: //class must have been added to library
0625: public final void instanciateObjectWorldFromLibrary(
0626: Class objectWorld, Avatar owner, Transform3D transform3D) {
0627:
0628: //instanciate object into the World Spot from the library
0629:
0630: Transaction transaction;
0631: Extent extent;
0632: Query query;
0633: String filter;
0634: Collection collection;
0635: Constructor[] constructors;
0636: Class[] classes;
0637: Object[] objects;
0638: ObjectWorld theObjectWorld;
0639:
0640: try {
0641: transaction = this .getPersistenceManager()
0642: .currentTransaction();
0643: transaction.begin();
0644:
0645: extent = this .getPersistenceManager().getExtent(
0646: objectWorld, true);
0647: filter = new String(
0648: "SELECT Class FROM Class c WHERE objectWorld.getClass()=c");
0649: query = this .getPersistenceManager().newQuery(objectWorld,
0650: extent, filter);
0651: collection = (Collection) query.execute();
0652:
0653: transaction.commit();
0654:
0655: //class is in library
0656: if (collection.size() > 0) {
0657:
0658: constructors = objectWorld.getDeclaredConstructors();
0659: classes = constructors[0].getParameterTypes();
0660: objects = new Object[2];
0661: objects[0] = this .getUniverseServer();
0662: objects[1] = owner;
0663: theObjectWorld = (ObjectWorld) constructors[0]
0664: .newInstance(objects);
0665: theObjectWorld.setTransform3D(transform3D);
0666: theObjectWorld.setPrice(0);
0667:
0668: try {
0669: transaction = this .getPersistenceManager()
0670: .currentTransaction();
0671: transaction.begin();
0672:
0673: this .getPersistenceManager().makePersistent(
0674: theObjectWorld);
0675:
0676: transaction.commit();
0677: } catch (Exception exception) {
0678: }
0679:
0680: }
0681:
0682: } catch (Exception exception) {
0683: }
0684:
0685: }
0686:
0687: //skins are a sub class of object world and could have been stored in the same library
0688: //however, skins have an affective attribute and are troublesome for users to be seen as objects
0689: //please use this method only for Skins, not for ObjectWorlds, BackgroundWorlds
0690: public final void addSkinToLibrary(Class skin) {
0691:
0692: int modifiers;
0693: Constructor[] constructors;
0694: Modifier modifier;
0695: Class[] classes;
0696: Transaction transaction;
0697:
0698: modifiers = skin.getModifiers();
0699: modifier = new Modifier();
0700: if (skin.isAssignableFrom(Skin.class)) {
0701: if (!(modifier.isAbstract(modifiers))
0702: && !(modifier.isPrivate(modifiers))
0703: && !(modifier.isInterface(modifiers))) {
0704: constructors = skin.getDeclaredConstructors();
0705: if (constructors.length > 0) {
0706: classes = constructors[0].getParameterTypes();
0707: if ((classes[0]
0708: .equals("[Lcom.db.server.UniverseServer"))
0709: && (classes[1]
0710: .equals("[Lcom.db.world.Avatar"))) {
0711: //add if not already added
0712: try {
0713: transaction = this .getPersistenceManager()
0714: .currentTransaction();
0715: transaction.begin();
0716:
0717: this .getPersistenceManager()
0718: .makePersistent(skin);
0719:
0720: transaction.commit();
0721: } catch (Exception exception) {
0722: }
0723:
0724: this .notifyFilterers(Filter.ADDITION, skin);
0725:
0726: }
0727: }
0728: }
0729: }
0730:
0731: }
0732:
0733: public final void removeSkinFromLibrary(Class skin) {
0734:
0735: //remove if exists
0736:
0737: Transaction transaction;
0738:
0739: try {
0740: transaction = this .getPersistenceManager()
0741: .currentTransaction();
0742: transaction.begin();
0743:
0744: this .getPersistenceManager().deletePersistent(skin);
0745:
0746: transaction.commit();
0747: } catch (Exception exception) {
0748: }
0749:
0750: this .notifyFilterers(Filter.DELETION, skin);
0751:
0752: }
0753:
0754: //price of the instanciated object should be 0
0755: //owner then sets up the price he wants to sell its skin if he really wants to sell
0756: //class must have been added to library
0757: public final void instanciateSkinFromLibrary(Class skin,
0758: Avatar owner, Transform3D transform3D) {
0759:
0760: //instanciate object into the World Spot from the library
0761:
0762: Transaction transaction;
0763: Extent extent;
0764: Query query;
0765: String filter;
0766: Collection collection;
0767: Constructor[] constructors;
0768: Class[] classes;
0769: Object[] objects;
0770: Skin theSkin;
0771:
0772: try {
0773: transaction = this .getPersistenceManager()
0774: .currentTransaction();
0775: transaction.begin();
0776:
0777: extent = this .getPersistenceManager().getExtent(skin, true);
0778: filter = new String(
0779: "SELECT Class FROM Class c WHERE skin.getClass()=c");
0780: query = this .getPersistenceManager().newQuery(skin, extent,
0781: filter);
0782: collection = (Collection) query.execute();
0783:
0784: transaction.commit();
0785:
0786: //class is in library
0787: if (collection.size() > 0) {
0788:
0789: constructors = skin.getDeclaredConstructors();
0790: classes = constructors[0].getParameterTypes();
0791: objects = new Object[2];
0792: objects[0] = this .getUniverseServer();
0793: objects[1] = owner;
0794: theSkin = (Skin) constructors[0].newInstance(objects);
0795: theSkin.setTransform3D(transform3D);
0796: theSkin.setPrice(0);
0797:
0798: try {
0799: transaction = this .getPersistenceManager()
0800: .currentTransaction();
0801: transaction.begin();
0802:
0803: this .getPersistenceManager()
0804: .makePersistent(theSkin);
0805:
0806: transaction.commit();
0807: } catch (Exception exception) {
0808: }
0809:
0810: }
0811:
0812: } catch (Exception exception) {
0813: }
0814:
0815: }
0816:
0817: //please use this method only for BackgroundWorlds, not for Skins, ObjectWorlds
0818: public final void addBackgroundWorldToLibrary(Class backgroundWorld) {
0819:
0820: int modifiers;
0821: Constructor[] constructors;
0822: Modifier modifier;
0823: Class[] classes;
0824: Transaction transaction;
0825:
0826: modifiers = backgroundWorld.getModifiers();
0827: modifier = new Modifier();
0828: if (backgroundWorld.isAssignableFrom(BackgroundWorld.class)) {
0829: if (!(modifier.isAbstract(modifiers))
0830: && !(modifier.isPrivate(modifiers))
0831: && !(modifier.isInterface(modifiers))) {
0832: constructors = backgroundWorld
0833: .getDeclaredConstructors();
0834: if (constructors.length > 0) {
0835: classes = constructors[0].getParameterTypes();
0836: if ((classes[0]
0837: .equals("[Lcom.db.server.UniverseServer"))
0838: && (classes[1]
0839: .equals("[Lcom.db.world.Avatar"))
0840: && (classes[2]
0841: .equals("[Ljavax.media.j3d.Bounds"))) {
0842: //add if not already added
0843: try {
0844: transaction = this .getPersistenceManager()
0845: .currentTransaction();
0846: transaction.begin();
0847:
0848: this .getPersistenceManager()
0849: .makePersistent(backgroundWorld);
0850:
0851: transaction.commit();
0852: } catch (Exception exception) {
0853: }
0854:
0855: this .notifyFilterers(Filter.ADDITION,
0856: backgroundWorld);
0857:
0858: }
0859: }
0860: }
0861: }
0862:
0863: }
0864:
0865: public final void removeBackgroundWorldFromLibrary(
0866: Class backgroundWorld) {
0867:
0868: //remove if exists
0869:
0870: Transaction transaction;
0871:
0872: try {
0873: transaction = this .getPersistenceManager()
0874: .currentTransaction();
0875: transaction.begin();
0876:
0877: this .getPersistenceManager().deletePersistent(
0878: backgroundWorld);
0879:
0880: transaction.commit();
0881:
0882: } catch (Exception exception) {
0883: }
0884:
0885: this .notifyFilterers(Filter.DELETION, backgroundWorld);
0886:
0887: }
0888:
0889: //price of the instanciated object should be 0
0890: //owner then sets up the price he wants to sell its backgroundWorld if he really wants to sell
0891: //class must have been added to library
0892: public final void instanciateBackgroundWorldFromLibrary(
0893: Class backgroundWorld, Avatar owner, Bounds bounds) {
0894:
0895: //instanciate object into the World Spot from the library
0896:
0897: Transaction transaction;
0898: Extent extent;
0899: Query query;
0900: String filter;
0901: Collection collection;
0902: Constructor[] constructors;
0903: Class[] classes;
0904: Object[] objects;
0905: BackgroundWorld theBackgroundWorld;
0906:
0907: try {
0908: transaction = this .getPersistenceManager()
0909: .currentTransaction();
0910: transaction.begin();
0911:
0912: extent = this .getPersistenceManager().getExtent(
0913: backgroundWorld, true);
0914: filter = new String(
0915: "SELECT Class FROM Class c WHERE backgroundWorld.getClass()=c");
0916: query = this .getPersistenceManager().newQuery(
0917: backgroundWorld, extent, filter);
0918: collection = (Collection) query.execute();
0919:
0920: transaction.commit();
0921:
0922: //class is in library
0923: if (collection.size() > 0) {
0924:
0925: constructors = backgroundWorld
0926: .getDeclaredConstructors();
0927: classes = constructors[0].getParameterTypes();
0928: objects = new Object[3];
0929: objects[0] = this .getUniverseServer();
0930: objects[1] = owner;
0931: objects[2] = bounds;
0932: theBackgroundWorld = (BackgroundWorld) constructors[0]
0933: .newInstance(objects);
0934: theBackgroundWorld.setPrice(0);
0935:
0936: try {
0937: transaction = this .getPersistenceManager()
0938: .currentTransaction();
0939: transaction.begin();
0940:
0941: this .getPersistenceManager().makePersistent(
0942: theBackgroundWorld);
0943:
0944: transaction.commit();
0945: } catch (Exception exception) {
0946: }
0947:
0948: }
0949:
0950: } catch (Exception exception) {
0951: }
0952:
0953: }
0954:
0955: //used for addidtion and deletion but NOT for read or write access
0956: private final void notifyFilterers(int accessKind,
0957: Class virtualElement) {
0958:
0959: Transaction transaction;
0960: Extent extent;
0961: Query query;
0962: String filter;
0963: Collection collection;
0964: Iterator iterator;
0965: Filter aFilter;
0966:
0967: try {
0968: transaction = this .getPersistenceManager()
0969: .currentTransaction();
0970: transaction.begin();
0971:
0972: extent = this .getPersistenceManager().getExtent(
0973: Filter.class, true);
0974: filter = new String(
0975: "SELECT Filter FROM Filter f WHERE f.getObject()==virtualElement");
0976: query = this .getPersistenceManager().newQuery(Filter.class,
0977: extent, filter);
0978: collection = (Collection) query.execute();
0979:
0980: transaction.commit();
0981:
0982: iterator = collection.iterator();
0983: while (iterator.hasNext()) {
0984: aFilter = (Filter) iterator.next();
0985: if (aFilter.getAccessKind() == accessKind) {
0986: if (accessKind == Filter.ADDITION) {
0987: this .getUniverseServer()
0988: .sendAdditionNotification(
0989: aFilter.getRequester(),
0990: virtualElement);
0991: } else {
0992: //Filter.DELETION
0993: this .getUniverseServer()
0994: .sendDeletionNotification(
0995: aFilter.getRequester(),
0996: virtualElement.hashCode());
0997: }
0998: }
0999: }
1000:
1001: } catch (Exception exception) {
1002: }
1003:
1004: }
1005:
1006: //must start with select
1007: public final HashSet queryWorldSpot(Avatar caller, String filter) {
1008:
1009: Transaction transaction;
1010: Extent extent;
1011: Query query;
1012: Collection collection;
1013:
1014: if (filter.regionMatches(0, "SELECT", 0, 6)) {
1015: try {
1016: transaction = this .getPersistenceManager()
1017: .currentTransaction();
1018: transaction.begin();
1019:
1020: extent = this .getPersistenceManager().getExtent(
1021: Object.class, true);
1022: query = this .getPersistenceManager().newQuery(
1023: Object.class, extent, filter);
1024: collection = (Collection) query.execute();
1025: transaction.commit();
1026:
1027: return this .filterCollection(caller, collection);
1028:
1029: } catch (Exception exception) {
1030:
1031: return null;
1032:
1033: }
1034: } else {
1035: return null;
1036: }
1037:
1038: }
1039:
1040: //convenience methods (queries the database with normal caller's rights)
1041:
1042: //the objects (tools and guides) currently on this world spot
1043: //(depending on the user's feudal rank, all avatars may not be displayed)
1044: //Collection of ObjectWorld (including skins)
1045: public final HashSet getObjectWorlds(Avatar caller) {
1046:
1047: Transaction transaction;
1048: Extent extent;
1049: Query query;
1050: String filter;
1051: Collection collection;
1052:
1053: try {
1054: transaction = this .getPersistenceManager()
1055: .currentTransaction();
1056: transaction.begin();
1057:
1058: extent = this .getPersistenceManager().getExtent(
1059: ObjectWorld.class, true);
1060: filter = new String("SELECT * FROM ObjectWorld");
1061: query = this .getPersistenceManager().newQuery(
1062: ObjectWorld.class, extent, filter);
1063: collection = (Collection) query.execute();
1064:
1065: transaction.commit();
1066:
1067: return this .filterCollection(caller, collection);
1068:
1069: } catch (Exception exception) {
1070:
1071: return null;
1072:
1073: }
1074:
1075: }
1076:
1077: //recursively get all vassals
1078: //equivalent to a query with "SELECT Avatar FROM Avatar a WHERE Avatar.getFeudalRelation(a, avatar)=Avatar.VASSAL;
1079: //but much faster
1080: public final HashSet getAllVassals(Avatar caller) {
1081:
1082: if (caller != null) {
1083: return this .filterCollection(caller, this .getAllVassals(
1084: caller.getVassals(), caller.getVassals()));
1085: } else {
1086: return null;
1087: }
1088:
1089: }
1090:
1091: private final HashSet getAllVassals(HashSet currentVassals,
1092: HashSet allVassals) {
1093:
1094: Iterator iterator;
1095: Avatar avatar;
1096: HashSet vassals;
1097: HashSet hashSet;
1098:
1099: if (currentVassals.size() > 0) {
1100: iterator = currentVassals.iterator();
1101: hashSet = new HashSet();
1102: while (iterator.hasNext()) {
1103: avatar = (Avatar) iterator.next();
1104: vassals = avatar.getVassals();
1105: if (vassals.size() > 0) {
1106: allVassals.addAll(vassals);
1107: hashSet.addAll(vassals);
1108: }
1109: }
1110: return this .getAllVassals(hashSet, allVassals);
1111: } else {
1112: return allVassals;
1113: }
1114:
1115: }
1116:
1117: //the avatars currently on this world spot
1118: //returns avatar with clients but also others (pawns...)
1119: //do a selective query to have only active clients
1120: //(depending on the user's feudal rank, all avatars may not be displayed)
1121: //Collection of Avatar
1122: //sorry but you can't get All avatars unless you are a ruler
1123: public final Collection getAvatars(Avatar caller) {
1124:
1125: Transaction transaction;
1126: Extent extent;
1127: Query query;
1128: String filter;
1129: Collection collection;
1130:
1131: if (caller != null) {
1132:
1133: try {
1134: transaction = this .getPersistenceManager()
1135: .currentTransaction();
1136: transaction.begin();
1137:
1138: extent = this .getPersistenceManager().getExtent(
1139: Avatar.class, true);
1140: filter = new String("SELECT * FROM Avatar");
1141: query = this .getPersistenceManager().newQuery(
1142: Avatar.class, extent, filter);
1143: collection = (Collection) query.execute();
1144:
1145: transaction.commit();
1146:
1147: return this .filterCollection(caller, collection);
1148:
1149: } catch (Exception exception) {
1150:
1151: return null;
1152:
1153: }
1154:
1155: } else {
1156: return null;
1157: }
1158:
1159: }
1160:
1161: //sorry but you can't get All avatars unless you are a ruler
1162: public final Collection getActiveAvatars(Avatar caller) {
1163:
1164: Transaction transaction;
1165: Extent extent;
1166: Query query;
1167: String filter;
1168: Collection collection;
1169:
1170: if (caller != null) {
1171:
1172: try {
1173: transaction = this .getPersistenceManager()
1174: .currentTransaction();
1175: transaction.begin();
1176:
1177: extent = this .getPersistenceManager().getExtent(
1178: Avatar.class, true);
1179: filter = new String(
1180: "SELECT * FROM Avatar a WHERE a.getStatus()==Avatar.NORMAL");
1181: query = this .getPersistenceManager().newQuery(
1182: Avatar.class, extent, filter);
1183: collection = (Collection) query.execute();
1184:
1185: transaction.commit();
1186:
1187: return this .filterCollection(caller, collection);
1188:
1189: } catch (Exception exception) {
1190:
1191: return null;
1192:
1193: }
1194:
1195: } else {
1196: return null;
1197: }
1198:
1199: }
1200:
1201: //the lands currently on this world spot
1202: //(depending on the user's feudal rank, all lands may not be displayed)
1203: //Collection of Land
1204: public final HashSet getLands(Avatar caller) {
1205:
1206: Transaction transaction;
1207: Extent extent;
1208: Query query;
1209: String filter;
1210: Collection collection;
1211:
1212: if (caller != null) {
1213:
1214: try {
1215: transaction = this .getPersistenceManager()
1216: .currentTransaction();
1217: transaction.begin();
1218:
1219: extent = this .getPersistenceManager().getExtent(
1220: Land.class, true);
1221: filter = new String("SELECT * FROM Land");
1222: query = this .getPersistenceManager().newQuery(
1223: Land.class, extent, filter);
1224: collection = (Collection) query.execute();
1225:
1226: transaction.commit();
1227:
1228: return this .filterCollection(caller, collection);
1229:
1230: } catch (Exception exception) {
1231:
1232: return null;
1233:
1234: }
1235:
1236: } else {
1237: return null;
1238: }
1239:
1240: }
1241:
1242: //the backgrounds currently on this world spot
1243: //(depending on the user's feudal rank, all backgrounds may not be displayed)
1244: //Collection of BackgoundWorld
1245: public final HashSet getBackgroundWorlds(Avatar caller) {
1246:
1247: Transaction transaction;
1248: Extent extent;
1249: Query query;
1250: String filter;
1251: Collection collection;
1252:
1253: if (caller != null) {
1254:
1255: try {
1256: transaction = this .getPersistenceManager()
1257: .currentTransaction();
1258: transaction.begin();
1259:
1260: extent = this .getPersistenceManager().getExtent(
1261: BackgroundWorld.class, true);
1262: filter = new String("SELECT * FROM BackgoundWorld");
1263: query = this .getPersistenceManager().newQuery(
1264: BackgroundWorld.class, extent, filter);
1265: collection = (Collection) query.execute();
1266:
1267: transaction.commit();
1268:
1269: return this .filterCollection(caller, collection);
1270:
1271: }
1272:
1273: catch (Exception exception) {
1274:
1275: return null;
1276:
1277: }
1278:
1279: } else {
1280: return null;
1281: }
1282: }
1283:
1284: private final static HashSet filterCollection(Avatar caller,
1285: Collection collection) {
1286:
1287: Iterator iterator;
1288: Iterator iterator2;
1289: Collection passCollection;
1290: HashSet resultCollection;
1291: int relation;
1292: VirtualElement virtualElement;
1293: boolean found;
1294: Pass pass;
1295:
1296: resultCollection = new HashSet();
1297:
1298: if (caller != null) {
1299:
1300: //objects with a pass may bypass access
1301: passCollection = caller.getPass();
1302:
1303: iterator = collection.iterator();
1304:
1305: while (iterator.hasNext()) {
1306:
1307: virtualElement = (VirtualElement) iterator.next();
1308: relation = Avatar.getFeudalRelation(caller,
1309: virtualElement.getUserOwner());
1310:
1311: if ((relation == Avatar.LORD)
1312: || (relation == Avatar.SELF)) {
1313: resultCollection.add(virtualElement);
1314: } else {
1315: if (virtualElement.getOthersAccessRights(relation) != VirtualElement.HIDDEN) {
1316: resultCollection.add(virtualElement);
1317: } else {
1318: iterator2 = passCollection.iterator();
1319: found = false;
1320: while (iterator2.hasNext() && (!found)) {
1321: pass = (Pass) iterator2.next();
1322: found = (pass.getObject() == virtualElement);
1323: }
1324: if (found) {
1325: resultCollection.add(virtualElement);
1326: }
1327: }
1328: }
1329:
1330: }
1331:
1332: }
1333:
1334: return resultCollection;
1335:
1336: }
1337:
1338: }
|