001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: /**
021: * An EmulatedFields is an object that represents a set of emulated fields for
022: * an object being dumped or loaded. It allows objects to be dumped with a shape
023: * different than the fields they were declared to have.
024: *
025: * @see ObjectInputStream.GetField
026: * @see ObjectOutputStream.PutField
027: * @see EmulatedFieldsForLoading
028: * @see EmulatedFieldsForDumping
029: */
030: class EmulatedFields {
031:
032: // A slot is a field plus its value
033: static class ObjectSlot {
034:
035: // Field descriptor
036: ObjectStreamField field;
037:
038: // Actual value this emulated field holds
039: Object fieldValue;
040:
041: // If this field has a default value (true) or something has been
042: // assigned (false)
043: boolean defaulted = true;
044:
045: /**
046: * Returns the descriptor for this emulated field.
047: *
048: * @return the field descriptor
049: */
050: public ObjectStreamField getField() {
051: return field;
052: }
053:
054: /**
055: * Returns the value held by this emulated field.
056: *
057: * @return the field value
058: */
059: public Object getFieldValue() {
060: return fieldValue;
061: }
062: }
063:
064: // The collection of slots the receiver represents
065: private ObjectSlot[] slotsToSerialize;
066:
067: private ObjectStreamField[] declaredFields;
068:
069: /**
070: * Constructs a new instance of EmulatedFields.
071: *
072: * @param fields
073: * an array of ObjectStreamFields, which describe the fields to
074: * be emulated (names, types, etc).
075: * @param declared
076: * an array of ObjectStreamFields, which describe the declared
077: * fields.
078: */
079: public EmulatedFields(ObjectStreamField[] fields,
080: ObjectStreamField[] declared) {
081: super ();
082: // We assume the slots are already sorted in the right shape for dumping
083: buildSlots(fields);
084: declaredFields = declared;
085: }
086:
087: /**
088: * Build emulated slots that correspond to emulated fields. A slot is a
089: * field descriptor (ObjectStreamField) plus the actual value it holds.
090: *
091: * @param fields
092: * an array of ObjectStreamField, which describe the fields to be
093: * emulated (names, types, etc).
094: */
095: private void buildSlots(ObjectStreamField[] fields) {
096: slotsToSerialize = new ObjectSlot[fields.length];
097: for (int i = 0; i < fields.length; i++) {
098: ObjectSlot s = new ObjectSlot();
099: slotsToSerialize[i] = s;
100: s.field = fields[i];
101: }
102: // We assume the slots are already sorted in the right shape for dumping
103: }
104:
105: /**
106: * Return a boolean indicating if the field named <code>name</code> has
107: * been assigned a value explicitly (false) or if it still holds a default
108: * value for the type (true) because it hasn't been assigned to yet.
109: *
110: * @param name
111: * a String, the name of the field to test
112: * @return <code>true</code> if <code>name</code> still holds its
113: * default value, <code>false</code> otherwise
114: *
115: * @throws IllegalArgumentException
116: * If <code>name</code> is null
117: */
118: public boolean defaulted(String name)
119: throws IllegalArgumentException {
120: ObjectSlot slot = findSlot(name, null);
121: if (slot == null) {
122: throw new IllegalArgumentException();
123: }
124: return slot.defaulted;
125: }
126:
127: /**
128: * Find and return an ObjectSlot that corresponds to a field named
129: * <code>fieldName</code> and type <code>fieldType</code>. If the field
130: * type <code>fieldType</code> corresponds to a primitive type, the field
131: * type has to match exactly or <code>null</code> is returned. If the
132: * field type <code>fieldType</code> corresponds to an object type, the
133: * field type has to be compatible in terms of assignment, or null is
134: * returned. If <code>fieldType</code> is <code>null</code>, no such
135: * compatibility checking is performed and the slot is returned.
136: *
137: * @param fieldName
138: * A String, the name of the field to find
139: * @param fieldType
140: * A Class, the type of the field. This will be used to test
141: * compatibility. If null, no testing is done, the corresponding
142: * slot is returned.
143: * @return If there is no field with that name, or no compatible field
144: * (relative to <code>fieldType</code>)
145: */
146: private ObjectSlot findSlot(String fieldName, Class<?> fieldType) {
147: boolean isPrimitive = fieldType != null
148: && fieldType.isPrimitive();
149:
150: for (int i = 0; i < slotsToSerialize.length; i++) {
151: ObjectSlot slot = slotsToSerialize[i];
152: if (slot.field.getName().equals(fieldName)) {
153: if (isPrimitive) {
154: // Looking for a primitive type field. Types must match
155: // *exactly*
156: if (slot.field.getType() == fieldType) {
157: return slot;
158: }
159: } else {
160: // Looking for a non-primitive type field.
161: if (fieldType == null) {
162: return slot; // Null means we take anything
163: }
164: // Types must be compatible (assignment)
165: if (slot.field.getType()
166: .isAssignableFrom(fieldType)) {
167: return slot;
168: }
169: }
170: }
171: }
172:
173: if (declaredFields != null) {
174: for (int i = 0; i < declaredFields.length; i++) {
175: ObjectStreamField field = declaredFields[i];
176: if (field.getName().equals(fieldName)) {
177: if (isPrimitive ? field.getType() == fieldType
178: : fieldType == null
179: || field
180: .getType()
181: .isAssignableFrom(fieldType)) {
182: ObjectSlot slot = new ObjectSlot();
183: slot.field = field;
184: slot.defaulted = true;
185: return slot;
186: }
187: }
188: }
189: }
190: return null;
191: }
192:
193: /**
194: * Find and return the byte value of a given field named <code>name</code>
195: * in the receiver. If the field has not been assigned any value yet, the
196: * default value <code>defaultValue</code> is returned instead.
197: *
198: * @param name
199: * A String, the name of the field to find
200: * @param defaultValue
201: * Return value in case the field has not been assigned to yet.
202: * @return the value of the given field if it has been assigned, the default
203: * value otherwise
204: *
205: * @throws IllegalArgumentException
206: * If the corresponding field can not be found.
207: */
208: public byte get(String name, byte defaultValue)
209: throws IllegalArgumentException {
210: ObjectSlot slot = findSlot(name, Byte.TYPE);
211: // if not initialized yet, we give the default value
212: if (slot == null) {
213: throw new IllegalArgumentException();
214: }
215: return slot.defaulted ? defaultValue : ((Byte) slot.fieldValue)
216: .byteValue();
217: }
218:
219: /**
220: * Find and return the char value of a given field named <code>name</code>
221: * in the receiver. If the field has not been assigned any value yet, the
222: * default value <code>defaultValue</code> is returned instead.
223: *
224: * @param name
225: * A String, the name of the field to find
226: * @param defaultValue
227: * Return value in case the field has not been assigned to yet.
228: * @return the value of the given field if it has been assigned, the default
229: * value otherwise
230: *
231: * @throws IllegalArgumentException
232: * If the corresponding field can not be found.
233: */
234: public char get(String name, char defaultValue)
235: throws IllegalArgumentException {
236: ObjectSlot slot = findSlot(name, Character.TYPE);
237: // if not initialized yet, we give the default value
238: if (slot == null) {
239: throw new IllegalArgumentException();
240: }
241: return slot.defaulted ? defaultValue
242: : ((Character) slot.fieldValue).charValue();
243: }
244:
245: /**
246: * Find and return the double value of a given field named <code>name</code>
247: * in the receiver. If the field has not been assigned any value yet, the
248: * default value <code>defaultValue</code> is returned instead.
249: *
250: * @param name
251: * A String, the name of the field to find
252: * @param defaultValue
253: * Return value in case the field has not been assigned to yet.
254: * @return the value of the given field if it has been assigned, the default
255: * value otherwise
256: *
257: * @throws IllegalArgumentException
258: * If the corresponding field can not be found.
259: */
260: public double get(String name, double defaultValue)
261: throws IllegalArgumentException {
262: ObjectSlot slot = findSlot(name, Double.TYPE);
263: // if not initialized yet, we give the default value
264: if (slot == null) {
265: throw new IllegalArgumentException();
266: }
267: return slot.defaulted ? defaultValue
268: : ((Double) slot.fieldValue).doubleValue();
269: }
270:
271: /**
272: * Find and return the float value of a given field named <code>name</code>
273: * in the receiver. If the field has not been assigned any value yet, the
274: * default value <code>defaultValue</code> is returned instead.
275: *
276: * @param name
277: * A String, the name of the field to find
278: * @param defaultValue
279: * Return value in case the field has not been assigned to yet.
280: * @return the value of the given field if it has been assigned, the default
281: * value otherwise
282: *
283: * @throws IllegalArgumentException
284: * If the corresponding field can not be found.
285: */
286: public float get(String name, float defaultValue)
287: throws IllegalArgumentException {
288: ObjectSlot slot = findSlot(name, Float.TYPE);
289: // if not initialized yet, we give the default value
290: if (slot == null) {
291: throw new IllegalArgumentException();
292: }
293: return slot.defaulted ? defaultValue
294: : ((Float) slot.fieldValue).floatValue();
295: }
296:
297: /**
298: * Find and return the int value of a given field named <code>name</code>
299: * in the receiver. If the field has not been assigned any value yet, the
300: * default value <code>defaultValue</code> is returned instead.
301: *
302: * @param name
303: * A String, the name of the field to find
304: * @param defaultValue
305: * Return value in case the field has not been assigned to yet.
306: * @return the value of the given field if it has been assigned, the default
307: * value otherwise
308: *
309: * @throws IllegalArgumentException
310: * If the corresponding field can not be found.
311: */
312: public int get(String name, int defaultValue)
313: throws IllegalArgumentException {
314: ObjectSlot slot = findSlot(name, Integer.TYPE);
315: // if not initialized yet, we give the default value
316: if (slot == null) {
317: throw new IllegalArgumentException();
318: }
319: return slot.defaulted ? defaultValue
320: : ((Integer) slot.fieldValue).intValue();
321: }
322:
323: /**
324: * Find and return the long value of a given field named <code>name</code>
325: * in the receiver. If the field has not been assigned any value yet, the
326: * default value <code>defaultValue</code> is returned instead.
327: *
328: * @param name
329: * A String, the name of the field to find
330: * @param defaultValue
331: * Return value in case the field has not been assigned to yet.
332: * @return the value of the given field if it has been assigned, the default
333: * value otherwise
334: *
335: * @throws IllegalArgumentException
336: * If the corresponding field can not be found.
337: */
338: public long get(String name, long defaultValue)
339: throws IllegalArgumentException {
340: ObjectSlot slot = findSlot(name, Long.TYPE);
341: // if not initialized yet, we give the default value
342: if (slot == null) {
343: throw new IllegalArgumentException();
344: }
345: return slot.defaulted ? defaultValue : ((Long) slot.fieldValue)
346: .longValue();
347: }
348:
349: /**
350: * Find and return the Object value of a given field named <code>name</code>
351: * in the receiver. If the field has not been assigned any value yet, the
352: * default value <code>defaultValue</code> is returned instead.
353: *
354: * @param name
355: * A String, the name of the field to find
356: * @param defaultValue
357: * Return value in case the field has not been assigned to yet.
358: * @return the value of the given field if it has been assigned, the default
359: * value otherwise
360: *
361: * @throws IllegalArgumentException
362: * If the corresponding field can not be found.
363: */
364: public Object get(String name, Object defaultValue)
365: throws IllegalArgumentException {
366: ObjectSlot slot = findSlot(name, null);
367: // if not initialized yet, we give the default value
368: if (slot == null || slot.field.getType().isPrimitive()) {
369: throw new IllegalArgumentException();
370: }
371: return slot.defaulted ? defaultValue : slot.fieldValue;
372: }
373:
374: /**
375: * Find and return the short value of a given field named <code>name</code>
376: * in the receiver. If the field has not been assigned any value yet, the
377: * default value <code>defaultValue</code> is returned instead.
378: *
379: * @param name
380: * A String, the name of the field to find
381: * @param defaultValue
382: * Return value in case the field has not been assigned to yet.
383: * @return the value of the given field if it has been assigned, the default
384: * value otherwise
385: *
386: * @throws IllegalArgumentException
387: * If the corresponding field can not be found.
388: */
389: public short get(String name, short defaultValue)
390: throws IllegalArgumentException {
391: ObjectSlot slot = findSlot(name, Short.TYPE);
392: // if not initialized yet, we give the default value
393: if (slot == null) {
394: throw new IllegalArgumentException();
395: }
396: return slot.defaulted ? defaultValue
397: : ((Short) slot.fieldValue).shortValue();
398: }
399:
400: /**
401: * Find and return the boolean value of a given field named
402: * <code>name</code> in the receiver. If the field has not been assigned
403: * any value yet, the default value <code>defaultValue</code> is returned
404: * instead.
405: *
406: * @param name
407: * A String, the name of the field to find
408: * @param defaultValue
409: * Return value in case the field has not been assigned to yet.
410: * @return the value of the given field if it has been assigned, the default
411: * value otherwise
412: *
413: * @throws IllegalArgumentException
414: * If the corresponding field can not be found.
415: */
416: public boolean get(String name, boolean defaultValue)
417: throws IllegalArgumentException {
418: ObjectSlot slot = findSlot(name, Boolean.TYPE);
419: // if not initialized yet, we give the default value
420: if (slot == null) {
421: throw new IllegalArgumentException();
422: }
423: return slot.defaulted ? defaultValue
424: : ((Boolean) slot.fieldValue).booleanValue();
425: }
426:
427: /**
428: * Find and set the byte value of a given field named <code>name</code> in
429: * the receiver.
430: *
431: * @param name
432: * A String, the name of the field to set
433: * @param value
434: * New value for the field.
435: *
436: * @throws IllegalArgumentException
437: * If the corresponding field can not be found.
438: */
439: public void put(String name, byte value)
440: throws IllegalArgumentException {
441: ObjectSlot slot = findSlot(name, Byte.TYPE);
442: if (slot == null) {
443: throw new IllegalArgumentException();
444: }
445: slot.fieldValue = Byte.valueOf(value);
446: slot.defaulted = false; // No longer default value
447: }
448:
449: /**
450: * Find and set the char value of a given field named <code>name</code> in
451: * the receiver.
452: *
453: * @param name
454: * A String, the name of the field to set
455: * @param value
456: * New value for the field.
457: *
458: * @throws IllegalArgumentException
459: * If the corresponding field can not be found.
460: */
461: public void put(String name, char value)
462: throws IllegalArgumentException {
463: ObjectSlot slot = findSlot(name, Character.TYPE);
464: if (slot == null) {
465: throw new IllegalArgumentException();
466: }
467: slot.fieldValue = Character.valueOf(value);
468: slot.defaulted = false; // No longer default value
469: }
470:
471: /**
472: * Find and set the double value of a given field named <code>name</code>
473: * in the receiver.
474: *
475: * @param name
476: * A String, the name of the field to set
477: * @param value
478: * New value for the field.
479: *
480: * @throws IllegalArgumentException
481: * If the corresponding field can not be found.
482: */
483: public void put(String name, double value)
484: throws IllegalArgumentException {
485: ObjectSlot slot = findSlot(name, Double.TYPE);
486: if (slot == null) {
487: throw new IllegalArgumentException();
488: }
489: slot.fieldValue = Double.valueOf(value);
490: slot.defaulted = false; // No longer default value
491: }
492:
493: /**
494: * Find and set the float value of a given field named <code>name</code>
495: * in the receiver.
496: *
497: * @param name
498: * A String, the name of the field to set
499: * @param value
500: * New value for the field.
501: *
502: * @throws IllegalArgumentException
503: * If the corresponding field can not be found.
504: */
505: public void put(String name, float value)
506: throws IllegalArgumentException {
507: ObjectSlot slot = findSlot(name, Float.TYPE);
508: if (slot == null) {
509: throw new IllegalArgumentException();
510: }
511: slot.fieldValue = Float.valueOf(value);
512: slot.defaulted = false; // No longer default value
513: }
514:
515: /**
516: * Find and set the int value of a given field named <code>name</code> in
517: * the receiver.
518: *
519: * @param name
520: * A String, the name of the field to set
521: * @param value
522: * New value for the field.
523: *
524: * @throws IllegalArgumentException
525: * If the corresponding field can not be found.
526: */
527: public void put(String name, int value)
528: throws IllegalArgumentException {
529: ObjectSlot slot = findSlot(name, Integer.TYPE);
530: if (slot == null) {
531: throw new IllegalArgumentException();
532: }
533: slot.fieldValue = Integer.valueOf(value);
534: slot.defaulted = false; // No longer default value
535: }
536:
537: /**
538: * Find and set the long value of a given field named <code>name</code> in
539: * the receiver.
540: *
541: * @param name
542: * A String, the name of the field to set
543: * @param value
544: * New value for the field.
545: *
546: * @throws IllegalArgumentException
547: * If the corresponding field can not be found.
548: */
549: public void put(String name, long value)
550: throws IllegalArgumentException {
551: ObjectSlot slot = findSlot(name, Long.TYPE);
552: if (slot == null) {
553: throw new IllegalArgumentException();
554: }
555: slot.fieldValue = Long.valueOf(value);
556: slot.defaulted = false; // No longer default value
557: }
558:
559: /**
560: * Find and set the Object value of a given field named <code>name</code>
561: * in the receiver.
562: *
563: * @param name
564: * A String, the name of the field to set
565: * @param value
566: * New value for the field.
567: *
568: * @throws IllegalArgumentException
569: * If the corresponding field can not be found.
570: */
571: public void put(String name, Object value)
572: throws IllegalArgumentException {
573: Class<?> valueClass = null;
574: if (value != null) {
575: valueClass = value.getClass();
576: }
577: ObjectSlot slot = findSlot(name, valueClass);
578: if (slot == null) {
579: throw new IllegalArgumentException();
580: }
581: slot.fieldValue = value;
582: slot.defaulted = false; // No longer default value
583: }
584:
585: /**
586: * Find and set the short value of a given field named <code>name</code>
587: * in the receiver.
588: *
589: * @param name
590: * A String, the name of the field to set
591: * @param value
592: * New value for the field.
593: *
594: * @throws IllegalArgumentException
595: * If the corresponding field can not be found.
596: */
597: public void put(String name, short value)
598: throws IllegalArgumentException {
599: ObjectSlot slot = findSlot(name, Short.TYPE);
600: if (slot == null) {
601: throw new IllegalArgumentException();
602: }
603: slot.fieldValue = Short.valueOf(value);
604: slot.defaulted = false; // No longer default value
605: }
606:
607: /**
608: * Find and set the boolean value of a given field named <code>name</code>
609: * in the receiver.
610: *
611: * @param name
612: * A String, the name of the field to set
613: * @param value
614: * New value for the field.
615: *
616: * @throws IllegalArgumentException
617: * If the corresponding field can not be found.
618: */
619: public void put(String name, boolean value)
620: throws IllegalArgumentException {
621: ObjectSlot slot = findSlot(name, Boolean.TYPE);
622: if (slot == null) {
623: throw new IllegalArgumentException();
624: }
625: slot.fieldValue = Boolean.valueOf(value);
626: slot.defaulted = false; // No longer default value
627: }
628:
629: /**
630: * Return the array of ObjectSlot the receiver represents.
631: *
632: * @return array of ObjectSlot the receiver represents.
633: */
634: public ObjectSlot[] slots() {
635: return slotsToSerialize;
636: }
637: }
|