Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/metacosm/util/LongProperty.java


1   /*
2       Metacosm, an object-oriented network game framework
3       Copyright (C) 1999-2001 Metacosm Development Team
4   
5       This program is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published by
7       the Free Software Foundation; either version 2 of the License, or
8       (at your option) any later version.
9   
10      This program is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13      GNU General Public License for more details.
14  
15      You should have received a copy of the GNU General Public License
16      along with this program; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19  
20  package org.metacosm.util;
21  
22  import java.util.List;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.Iterator;
26  
27  /**
28   * A Property with long value.
29   * TODO: min and max values can be stored in a memory-friendly way.
30   * They aren't stored as two long or double * values but as a special immutable Interval
31   * object (in fact a * reference to this object). A hashtable links (min, max) couples to
32   * IntervalManager objects, so for a given interval, only one Interval exists.
33   */
34  public final class LongProperty extends Property {
35  
36    /**
37     * LongProperty constructor without a specified interval.
38     * Interval is defined as encompassing all long values.
39     * @param name the name of property
40     * @param value the value of the property
41     * @throws IllegalArgumentException if name is null
42     */
43    public LongProperty(String name, long value) throws IllegalArgumentException {
44      this( name, value, Long.MIN_VALUE, Long.MAX_VALUE);
45    }
46  
47    /**
48     * LongProperty constructor with a specified interval.
49     * @param name the name of the property
50     * @param value the value of the property
51     * @param min the min value of the interval
52     * @param max the max value of the interval
53     * @throws IllegalArgumentException if name is null, or if min and max values are not in the right order.
54     */
55    public LongProperty(String name, long value, long min, long max) throws IllegalArgumentException {
56      super(name);
57      if (min > max) {
58        throw new IllegalArgumentException();
59      }
60      interval = new LongInterval(min, max);
61      this.value = interval.boundedValue(value);
62      initialValue = this.value;
63      absList = Collections.synchronizedList(new ArrayList());
64      randomValues = Collections.synchronizedList(new ArrayList());
65      absModifier = null;
66      relDelta = 0;
67      valueIndex = -1;
68    }
69  
70    /**
71     * Used by clone() to produce a property with the same name and value, and with
72     * the same shared interval.
73     */
74    private LongProperty(String name, long value, LongInterval interval) {
75      super(name);
76      this.interval = interval;
77      this.value = value;
78      initialValue = this.value;
79      absList = Collections.synchronizedList(new ArrayList());
80      randomValues = Collections.synchronizedList(new ArrayList());
81      absModifier = null;
82      relDelta = 0;
83      valueIndex = -1;
84    }
85  
86    public Object getValue() {
87      return new Long(value);
88    }
89  
90    public long getLongValue() {
91      return value;
92    }
93  
94    public long getMinValue() {
95      return interval.getMin();
96    }
97  
98    public long getMaxValue() {
99      return interval.getMax();
100   }
101 
102   private void calculate() {
103     if (absModifier != null) {
104       if (valueIndex < 0) {
105         value = interval.boundedValue( ((Long)absModifier.getValue()).longValue() + relDelta);
106       } else {
107         value = interval.boundedValue( ((Long)randomValues.get( valueIndex)).longValue() + relDelta);
108       }
109     } else {
110       valueIndex = -1;
111       value = interval.boundedValue( initialValue + relDelta);
112     }
113   }
114 
115   /**
116    * Applies an absolute modifier to the property.
117    * If the absolute modifier has the highest priority,
118    * property value is computed anew, and then bounded.
119    * @param absMod the absolute modifier to be applied
120    */
121   public synchronized void applyModifier(AbsoluteModifier absMod) {
122     if (absMod != null) {
123       Long randomValue = null;
124       if (absMod instanceof RandomAbsoluteModifier) {
125         randomValue = (Long)absMod.getValue();
126         randomValues.add( randomValue);
127       }
128       absList.add(absMod);
129       if (absModifier == null || (absMod.getPriority() > absModifier.getPriority())) {
130         absModifier = absMod;
131         if (randomValue != null) {
132           valueIndex = randomValues.size()-1;
133         }
134         calculate();
135       }
136     }
137   }
138 
139   /**
140    * Applies a relative modifier to the property.
141    * Property value is computed anew, and then bounded.
142    * @param relMod the relative modifier to be applied
143    */
144   public synchronized void applyModifier(RelativeModifier relMod) {
145     if (relMod != null) {
146       relDelta += ((Long)relMod.getValue()).longValue();
147       calculate();
148     }
149   }
150 
151   /**
152    * Removes an absolute modifier previously applied to the property.
153    * Absolute modifier list is updated, and a new absolute modifier
154    * is chosen according to priority. Property value is then computed anew.
155    * @param absMod the absolute modifier to be removed
156    */
157   public synchronized void removeModifier(AbsoluteModifier absMod) {
158     if (absList.remove(absMod) && absMod == absModifier) {
159       long maxPriority = Integer.MIN_VALUE;
160       absModifier = null;
161       int ramCpt = -1;
162       boolean isRam = false;
163       valueIndex = -1;
164       for (Iterator i = absList.iterator(); i.hasNext(); ) {
165         AbsoluteModifier current = ((AbsoluteModifier)i.next());
166         isRam = (current instanceof RandomAbsoluteModifier);
167         if (isRam) {
168           ++ramCpt;
169         }
170         int priority = current.getPriority();
171         if (priority > maxPriority) {
172           if (isRam) {
173             valueIndex = ramCpt;
174           } else {
175             valueIndex = -1;
176           }
177           maxPriority = priority;
178           absModifier = current;
179         }
180       }
181       calculate();
182     }
183   }
184 
185   /**
186    * Removes a relative modifier previously applied to the property.
187    * Property value is computed anew, and then bounded.
188    * @param relMod the relative modifier to be removed
189    */
190   public synchronized void removeModifier(RelativeModifier relMod) {
191     if (relMod != null) {
192       relDelta -= ((Long)relMod.getValue()).longValue();
193       calculate();
194     }
195   }
196 
197   public void save(java.io.OutputStream os) throws java.io.IOException {
198     // serialization for now
199     /*
200     new java.io.ObjectOutputStream( os).writeObject( this);
201     */
202   }
203 
204   public void load(java.io.InputStream is) throws java.io.IOException {
205     // serialization for now
206     /*
207     java.io.ObjectInputStream ois = new java.io.ObjectInputStream( is);
208     try {
209       LongProperty lp = (LongProperty) ois.readObject();
210       this.value = lp.value;
211       this.initialValue = lp.initialValue;
212       this.absList = lp.absList;
213       this.maxPriority = lp.maxPriority;
214       this.relDelta = lp.relDelta;
215       this.interval = lp.interval;
216     } catch ( ClassNotFoundException e) {
217       throw new UnsupportedOperationException();
218     }
219     */
220   }
221 
222   public String toString() {
223     StringBuffer sb = new StringBuffer( "   " + value + " [" + interval.getMin() + "," + interval.getMax() + "]\n   ");
224     sb.append("absModifier = " + absModifier + "\n   initialValue = " + initialValue + "\n   absList = ");
225     for (Iterator i = absList.iterator(); i.hasNext(); ) {
226       AbsoluteModifier am = (AbsoluteModifier)i.next();
227       sb.append( "(" + am + ") ");
228     }
229     sb.append("\n   randomValues = ");
230     for (Iterator i = randomValues.iterator(); i.hasNext(); ) {
231       sb.append( i.next() + " ");
232     }
233     sb.append( "\n   relDelta = " + relDelta + "\n   valueIndex = " + valueIndex);
234     return new String(sb);
235   }
236 
237   /**
238    * @return a new LongProperty with the same name, value and interval. Interval is
239    * the same shared object.
240    */
241   public Object clone() {
242     return new LongProperty(name, value, interval);
243   }
244 
245   private long value;
246   private long initialValue;
247 
248   /**
249    * AbsoluteModifiers list
250    */
251   private List absList;
252   /**
253    * RandomAbsoluteModifier values list
254    */
255   private List randomValues;
256   /**
257    * The first max priority AbsoluteModifier
258    */
259   private AbsoluteModifier absModifier;
260   /**
261    * RandomAbsoluteModifier value index (for the first max priority AbsoluteModifier)
262    * -1 if not a RandomAbsoluteModifier<br>
263    * &gt;= 0 otherwise
264    */
265   int valueIndex;
266   /**
267    * RelativeModifiers final effect
268    */
269   private long relDelta;
270   /**
271    * Domain interval
272    */
273   private LongInterval interval;
274 }
275