Source Code Cross Referenced for Conversion.java in  » JMX » je » com » sleepycat » persist » evolve » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » je » com.sleepycat.persist.evolve 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: Conversion.java,v 1.9.2.3 2008/01/07 15:14:19 cwl Exp $
007:         */
008:
009:        package com.sleepycat.persist.evolve;
010:
011:        import java.io.Serializable;
012:
013:        import com.sleepycat.persist.model.EntityModel;
014:        import com.sleepycat.persist.raw.RawObject;
015:        import com.sleepycat.persist.raw.RawType;
016:
017:        /**
018:         * Converts an old version of an object value to conform to the current class
019:         * or field definition.
020:         *
021:         * <p>The {@code Conversion} interface is implemented by the user.  A
022:         * {@code Conversion} instance is passed to the {@link Converter#Converter}
023:         * constructor.</p>
024:         *
025:         * <p>The {@code Conversion} interface extends {@link Serializable} and the
026:         * {@code Conversion} instance is serialized for storage using standard Java
027:         * serialization.  Normally, the {@code Conversion} class should only have
028:         * transient fields that are initialized in the {@link #initialize} method.
029:         * While non-transient fields are allowed, care must be taken to only include
030:         * fields that are serializable and will not pull in large amounts of data.</p>
031:         *
032:         * <p>When a class conversion is specified, two special considerations
033:         * apply:</p>
034:         * <ol>
035:         * <li>A class conversion is only applied when to instances of that class.  The
036:         * conversion will not be applied when the class when it appears as a
037:         * superclass of the instance's class.  In this case, a conversion for the
038:         * instance's class must also be specified.</li>
039:         * <li>Although field renaming (as well as all other changes) is handled by the
040:         * conversion method, a field Renamer is still needed when a secondary key
041:         * field is renamed and field Deleter is still needed when a secondary key
042:         * field is deleted.  This is necessary for evolution of the metadata;
043:         * specifically, if the key name changes the database must be renamed and if
044:         * the key field is deleted the secondary database must be deleted.</li>
045:         * </ol>
046:         *
047:         * <p>The {@code Conversion} class must implement the standard equals method.
048:         * See {@link #equals} for more information.</p>
049:         *
050:         * <p>Conversions of simple types are generally simple.  For example, a {@code
051:         * String} field that contains only integer values can be easily converted to
052:         * an {@code int} field:</p>
053:         * <pre class="code">
054:         *  // The old class.  Version 0 is implied.
055:         *  //
056:         *  {@literal @Persistent}
057:         *  class Address {
058:         *      String zipCode;
059:         *      ...
060:         *  }
061:         *
062:         *  // The new class.  A new version number must be assigned.
063:         *  //
064:         *  {@literal @Persistent(version=1)}
065:         *  class Address {
066:         *      int zipCode;
067:         *      ...
068:         *  }
069:         *
070:         *  // The conversion class.
071:         *  //
072:         *  class MyConversion1 implements Conversion {
073:         *
074:         *      public void initialize(EntityModel model) {
075:         *          // No initialization needed.
076:         *      }
077:         *
078:         *      public Object convert(Object fromValue) {
079:         *          return Integer.valueOf((String) fromValue);
080:         *      }
081:         *
082:         *      {@code @Override}
083:         *      public boolean equals(Object o) {
084:         *          return o instanceof MyConversion1;
085:         *      }
086:         *  }
087:         *
088:         *  // Create a field converter mutation.
089:         *  //
090:         *  Converter converter = new Converter(Address.class.getName(), 0,
091:         *                                      "zipCode", new MyConversion1());
092:         *
093:         *  // Configure the converter as described {@link Mutations here}.</pre>
094:         *
095:         * <p>A conversion may perform arbitrary transformations on an object.  For
096:         * example, a conversion may transform a single String address field into an
097:         * Address object containing four fields for street, city, state and zip
098:         * code.</p>
099:         * <pre class="code">
100:         *  // The old class.  Version 0 is implied.
101:         *  //
102:         *  {@literal @Entity}
103:         *  class Person {
104:         *      String address;
105:         *      ...
106:         *  }
107:         *
108:         *  // The new class.  A new version number must be assigned.
109:         *  //
110:         *  {@literal @Entity(version=1)}
111:         *  class Person {
112:         *      Address address;
113:         *      ...
114:         *  }
115:         *
116:         *  // The new address class.
117:         *  //
118:         *  {@literal @Persistent}
119:         *  class Address {
120:         *      String street;
121:         *      String city;
122:         *      String state;
123:         *      int zipCode;
124:         *      ...
125:         *  }
126:         *
127:         *  class MyConversion2 implements Conversion {
128:         *      private transient RawType addressType;
129:         *
130:         *      public void initialize(EntityModel model) {
131:         *          addressType = model.getRawType(Address.class.getName());
132:         *      }
133:         *
134:         *      public Object convert(Object fromValue) {
135:         *
136:         *          // Parse the old address and populate the new address fields
137:         *          //
138:         *          String oldAddress = (String) fromValue;
139:         *          {@literal Map<String,Object> addressValues = new HashMap<String,Object>();}
140:         *          addressValues.put("street", parseStreet(oldAddress));
141:         *          addressValues.put("city", parseCity(oldAddress));
142:         *          addressValues.put("state", parseState(oldAddress));
143:         *          addressValues.put("zipCode", parseZipCode(oldAddress));
144:         *
145:         *          // Return new raw Address object
146:         *          //
147:         *          return new RawObject(addressType, addressValues, null);
148:         *      }
149:         *
150:         *      {@code @Override}
151:         *      public boolean equals(Object o) {
152:         *          return o instanceof MyConversion2;
153:         *      }
154:         *
155:         *      private String parseStreet(String oldAddress) { ... }
156:         *      private String parseCity(String oldAddress) { ... }
157:         *      private String parseState(String oldAddress) { ... }
158:         *      private Integer parseZipCode(String oldAddress) { ... }
159:         *  }
160:         *
161:         *  // Create a field converter mutation.
162:         *  //
163:         *  Converter converter = new Converter(Person.class.getName(), 0,
164:         *                                      "address", new MyConversion2());
165:         *
166:         *  // Configure the converter as described {@link Mutations here}.</pre>
167:         *
168:         * <p>Note that when a conversion returns a {@link RawObject}, it must return
169:         * it with a {@link RawType} that is current as defined by the current class
170:         * definitions.  The proper types can be obtained from the {@link EntityModel}
171:         * in the conversion's {@link #initialize initialize} method.</p>
172:         *
173:         * <p>A variation on the example above is where several fields in a class
174:         * (street, city, state and zipCode) are converted to a single field (address).
175:         * In this case a class converter rather than a field converter is used.</p>
176:         *
177:         * <pre class="code">
178:         *  // The old class.  Version 0 is implied.
179:         *  //
180:         *  {@literal @Entity}
181:         *  class Person {
182:         *      String street;
183:         *      String city;
184:         *      String state;
185:         *      int zipCode;
186:         *      ...
187:         *  }
188:         *
189:         *  // The new class.  A new version number must be assigned.
190:         *  //
191:         *  {@literal @Entity(version=1)}
192:         *  class Person {
193:         *      Address address;
194:         *      ...
195:         *  }
196:         *
197:         *  // The new address class.
198:         *  //
199:         *  {@literal @Persistent}
200:         *  class Address {
201:         *      String street;
202:         *      String city;
203:         *      String state;
204:         *      int zipCode;
205:         *      ...
206:         *  }
207:         *
208:         *  class MyConversion3 implements Conversion {
209:         *      private transient RawType newPersonType;
210:         *      private transient RawType addressType;
211:         *
212:         *      public void initialize(EntityModel model) {
213:         *          newPersonType = model.getRawType(Person.class.getName());
214:         *          addressType = model.getRawType(Address.class.getName());
215:         *      }
216:         *
217:         *      public Object convert(Object fromValue) {
218:         *
219:         *          // Get field value maps for old and new objects.
220:         *          //
221:         *          RawObject person = (RawObject) fromValue;
222:         *          {@literal Map<String,Object> personValues = person.getValues();}
223:         *          {@literal Map<String,Object> addressValues = new HashMap<String,Object>();}
224:         *          RawObject address = new RawObject(addressType, addressValues, null);
225:         *
226:         *          // Remove the old address fields and insert the new one.
227:         *          //
228:         *          addressValues.put("street", personValues.remove("street"));
229:         *          addressValues.put("city", personValues.remove("city"));
230:         *          addressValues.put("state", personValues.remove("state"));
231:         *          addressValues.put("zipCode", personValues.remove("zipCode"));
232:         *          personValues.put("address", address);
233:         *
234:         *          return new RawObject(newPersonType, personValues, person.getSuper());
235:         *      }
236:         *
237:         *      {@code @Override}
238:         *      public boolean equals(Object o) {
239:         *          return o instanceof MyConversion3;
240:         *      }
241:         *  }
242:         *
243:         *  // Create a class converter mutation.
244:         *  //
245:         *  Converter converter = new Converter(Person.class.getName(), 0,
246:         *                                      new MyConversion3());
247:         *
248:         *  // Configure the converter as described {@link Mutations here}.</pre>
249:         *
250:         *
251:         * <p>A conversion can also handle changes to class hierarchies.  For example,
252:         * if a "name" field originally declared in class A is moved to its superclass
253:         * B, a conversion can move the field value accordingly:</p>
254:         *
255:         * <pre class="code">
256:         *  // The old classes.  Version 0 is implied.
257:         *  //
258:         *  {@literal @Persistent}
259:         *  class A extends B {
260:         *      String name;
261:         *      ...
262:         *  }
263:         *  {@literal @Persistent}
264:         *  abstract class B {
265:         *      ...
266:         *  }
267:         *
268:         *  // The new classes.  A new version number must be assigned.
269:         *  //
270:         *  {@literal @Persistent(version=1)}
271:         *  class A extends B {
272:         *      ...
273:         *  }
274:         *  {@literal @Persistent(version=1)}
275:         *  abstract class B {
276:         *      String name;
277:         *      ...
278:         *  }
279:         *
280:         *  class MyConversion4 implements Conversion {
281:         *      private transient RawType newAType;
282:         *      private transient RawType newBType;
283:         *
284:         *      public void initialize(EntityModel model) {
285:         *          newAType = model.getRawType(A.class.getName());
286:         *          newBType = model.getRawType(B.class.getName());
287:         *      }
288:         *
289:         *      public Object convert(Object fromValue) {
290:         *          RawObject oldA = (RawObject) fromValue;
291:         *          RawObject oldB = oldA.getSuper();
292:         *          {@literal Map<String,Object> aValues = oldA.getValues();}
293:         *          {@literal Map<String,Object> bValues = oldB.getValues();}
294:         *          bValues.put("name", aValues.remove("name"));
295:         *          RawObject newB = new RawObject(newBType, bValues, oldB.getSuper());
296:         *          RawObject newA = new RawObject(newAType, aValues, newB);
297:         *          return newA;
298:         *      }
299:         *
300:         *      {@code @Override}
301:         *      public boolean equals(Object o) {
302:         *          return o instanceof MyConversion4;
303:         *      }
304:         *  }
305:         *
306:         *  // Create a class converter mutation.
307:         *  //
308:         *  Converter converter = new Converter(A.class.getName(), 0,
309:         *                                      new MyConversion4());
310:         *
311:         *  // Configure the converter as described {@link Mutations here}.</pre>
312:         *
313:         * <p>A conversion may return an instance of a different class entirely, as
314:         * long as it conforms to current class definitions and is the type expected
315:         * in the given context (a subtype of the old type, or a type compatible with
316:         * the new field type).  For example, a field that is used to discriminate
317:         * between two types of objects could be removed and replaced by two new
318:         * subclasses:</p> <pre class="code">
319:         *  // The old class.  Version 0 is implied.
320:         *  //
321:         *  {@literal @Persistent}
322:         *  class Pet {
323:         *      boolean isCatNotDog;
324:         *      ...
325:         *  }
326:         *
327:         *  // The new classes.  A new version number must be assigned to the Pet class.
328:         *  //
329:         *  {@literal @Persistent(version=1)}
330:         *  class Pet {
331:         *      ...
332:         *  }
333:         *  {@literal @Persistent}
334:         *  class Cat extends Pet {
335:         *      ...
336:         *  }
337:         *  {@literal @Persistent}
338:         *  class Dog extends Pet {
339:         *      ...
340:         *  }
341:         *
342:         *  class MyConversion5 implements Conversion {
343:         *      private transient RawType newPetType;
344:         *      private transient RawType dogType;
345:         *      private transient RawType catType;
346:         *
347:         *      public void initialize(EntityModel model) {
348:         *          newPetType = model.getRawType(Pet.class.getName());
349:         *          dogType = model.getRawType(Dog.class.getName());
350:         *          catType = model.getRawType(Cat.class.getName());
351:         *      }
352:         *
353:         *      public Object convert(Object fromValue) {
354:         *          RawObject pet = (RawObject) fromValue;
355:         *          {@literal Map<String,Object> petValues = pet.getValues();}
356:         *          Boolean isCat = (Boolean) petValues.remove("isCatNotDog");
357:         *          RawObject newPet = new RawObject(newPetType, petValues,
358:         *                                           pet.getSuper());
359:         *          RawType newSubType = isCat ? catType : dogType;
360:         *          return new RawObject(newSubType, Collections.emptyMap(), newPet);
361:         *      }
362:         *
363:         *      {@code @Override}
364:         *      public boolean equals(Object o) {
365:         *          return o instanceof MyConversion5;
366:         *      }
367:         *  }
368:         *
369:         *  // Create a class converter mutation.
370:         *  //
371:         *  Converter converter = new Converter(Pet.class.getName(), 0,
372:         *                                      new MyConversion5());
373:         *
374:         *  // Configure the converter as described {@link Mutations here}.</pre>
375:         *
376:         * <p>The primary limitation of a conversion is that it may access at most a
377:         * single entity instance at one time.  Conversions involving multiple entities
378:         * at once may be made by performing a <a
379:         * href="package-summary.html#storeConversion">store conversion</a>.</p>
380:         *
381:         * @see com.sleepycat.persist.evolve Class Evolution
382:         * @author Mark Hayes
383:         */
384:        public interface Conversion extends Serializable {
385:
386:            /**
387:             * Initializes the conversion, allowing it to obtain raw type information
388:             * from the entity model.
389:             */
390:            void initialize(EntityModel model);
391:
392:            /**
393:             * Converts an old version of an object value to conform to the current
394:             * class or field definition.
395:             *
396:             * <p>If a {@link RuntimeException} is thrown by this method, it will be
397:             * thrown to the original caller.  Similarly, a {@link
398:             * IllegalArgumentException} will be thrown to the original caller if the
399:             * object returned by this method does not conform to current class
400:             * definitions.</p>
401:             *
402:             * <p>The class of the input and output object may be one of the simple
403:             * types or {@link RawObject}.  For primitive types, the primitive wrapper
404:             * class is used.</p>
405:             *
406:             * @param fromValue the object value being converted.  The type of this
407:             * value is defined by the old class version that is being converted.
408:             *
409:             * @return the converted object.  The type of this value must conform to
410:             * a current class definition.  If this is a class conversion, it must
411:             * be the current version of the class.  If this is a field conversion, it
412:             * must be of a type compatible with the current declared type of the
413:             * field.
414:             */
415:            Object convert(Object fromValue);
416:
417:            /**
418:             * The standard {@code equals} method that must be implemented by
419:             * conversion class.
420:             *
421:             * <p>When mutations are specified when opening a store, the specified and
422:             * previously stored mutations are compared for equality.  If they are
423:             * equal, there is no need to replace the existing mutations in the stored
424:             * catalog.  To accurately determine equality, the conversion class must
425:             * implement the {@code equals} method.</p>
426:             *
427:             * <p>If the {@code equals} method is not explicitly implemented by the
428:             * conversion class or a superclass other than {@code Object}, {@code
429:             * IllegalArgumentException} will be thrown when the store is opened.</p>
430:             *
431:             * <p>Normally whenever {@code equals} is implemented the {@code hashCode}
432:             * method should also be implemented to support hash sets and maps.
433:             * However, hash sets and maps containing <code>Conversion</code> objects
434:             * are not used by the DPL and therefore the DPL does not require
435:             * {@code hashCode} to be implemented.</p>
436:             */
437:            boolean equals(Object other);
438:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.