Javolution

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 » Development » Javolution 
Javolution
License:
URL:http://javolution.org/
Description:Javolution real-time goals are simple: To make your application faster and more time predictable!
Package NameComment
j2me.io
j2me.lang
j2me.nio
j2me.text
j2me.util
j2me.util.concurrent
j2me.util.logging
j2me.util.zip
j2mex.realtime
javolution
javolution.context

Provides real-time {@link javolution.context.Context} to facilitate separation of concerns and achieve higher level of performance and code predictability.

Separation of Concerns

Separation of concerns is an important design principle greatly misenderstood. Most developers think it is limited to modularity and encapsulation or it requires special programming tools (e.g. Aspect programming).

Separation of concerns is very powerful and easier than it looks. Basically, it could be summarized as the "pass the buck principle". If you don't know what to do with some information, just give it to someone else who might know.

A frequent example is the catching of exceptions too early (with some logging processing) instead of throwing a checked exception. Unfortunately, they are still plenty of cases where the separation of concerns is not as good as it could be. For example logging! Using the standard logging, the code has to know which logger to log to? Why?

Separation of concerns can be adressed through "Aspect Programming", but there is a rather simpler solution "Context Programming"!

It does not require any particular tool, it basically says that every threads has a context which can be customized by someone else (the one who knows what to do). Then, your code looks a lot cleaner and is way more flexible as you don't have to worry about logging, security, performance etc. in your low level methods. For example:[code] void myMethod() { ... LogContext.info("Don't know where this is going to be logged to"); ... }[/code]

Used properly Javolution's {@link javolution.context.Context contexts} greatly facilitate the separation of concerns. Contexts are complemented by others classes such as for example the {@link javolution.lang.Configurable Configurable} class to reduce dependency between configuration and application code.

Predefined Contexts:

This package provides few predefined contexts:

  • {@link javolution.context.LocalContext LocalContext} - To define locally scoped environment settings.
  • {@link javolution.context.ConcurrentContext ConcurrentContext} - To take advantage of concurrent algorithms on multi-processors systems.
  • {@link javolution.context.AllocatorContext AllocatorContext} - To control object allocation, e.g. {@link javolution.context.StackContext StackContext} to allocate on the stack (or RTSJ ScopedMemory).
  • {@link javolution.context.LogContext LogContext} - For thread-based or object-based logging capability, e.g. {@link javolution.util.StandardLog StandardLog} to leverage standard logging capabilities. Note: java.util.logging provides class-based logging (based upon class hierarchy).
  • {@link javolution.context.PersistentContext PersistentContext} - To achieve persistency across multiple program execution.
  • {@link javolution.context.SecurityContext SecurityContext} - To address application-level security concerns.
  • {@link javolution.testing.TestContext TestContext} - To address varied aspect of testing such as performance and regression.

FAQ:

  1. I am writing an application using third party libraries. I cannot avoid GC unless I get the source and patch it to Javolution. Can I still make my application real-time using {@link javolution.context.StackContext StackContext}?

    You cannot get determinism using "any" library (including Java standard library) regardless of the garbage collector issue. Array resizing, lazy initialization, map rehashing (...) would all introduce unexpected delays (this is why Javolution comes with its own {@link javolution.lang.Realtime real-time} collections implementation). Still, you may use incremental/real-time collectors (if few milliseconds delays are acceptable). These collectors work even faster if you limit the amount of garbage produced onto the heap through {@link javolution.context.StackContext stack allocations}.

  2. Can you explain a little how objects can be "stack" allocated?

    It all depends upon the StackContext {@link javolution.context.StackContext#DEFAULT default} implementation. The default implementation use thread-local queues (no synchronization required); but if you run on a RTSJ virtual machine entering a {@link javolution.context.StackContext StackContext} could mean using ScopedMemory.

  3. As a rule, I am skeptical of classes that pool small objects. At one time (5 years ago) it was a big win. Over time, the advantage has diminished as garbage collectors improve. Object pools can make it much more difficult for the garbage collector to do its job efficiently, and can have adverse effects on footprint. (Joshua Bloch)

    Stack allocation is different from object pooling, it is a simple and transparent way to make your methods "clean" (no garbage generated), it has also the side effect of making your methods faster and more time-predictable. If all your methods are "clean" then your whole application is "clean", faster and more time-predictable (aka real-time).

    In practice very few methods need to enter a {@link javolution.context.StackContext StackContext}, only the one generating a significant number of temporary objects (these methods are made "cleaner" and faster through stack allocation). For example:[code] public final class DenseVector> extends Vector { ... public F times(Vector that) { final int n = this.getDimension(); if (that.getDimension() != n) throw new DimensionException(); StackContext.enter(); try { // Reduces memory allocation / garbage collection. F sum = this.get(0).times(that.get(0)); for (int i = 1; i < n; i++) { sum = sum.plus(this.get(i).times(that.get(i))); } return StackContext.outerCopy(sum); // Stack object exported through copy. } finally { StackContext.exit(); // Resets stack. } } ... }[/code]

javolution.io

Provides utility classes for input and output (such as {@link javolution.io.Struct Struct} and {@link javolution.io.Union Union} for direct interoperability with C/C++).

javolution.lang

Provides fundamental classes and interfaces; some of which are either missing from the java.lang package or are not available for all platforms (including J2ME CLDC).

javolution.testing

Provides classes and interfaces to facilitate all aspects of testing including unit tests, performance, regression, etc.

Too often unit tests focus on one aspect: "Validation". But although a code modification might not break your application; it may very well impact the performance significantly (for the better or the worst). External elements (JVM, O/S, memory available, runtime options) are also likely to affect performance. It is therefore important to not only be able to measure the performance but also to detect automatically (regression tests) when any change you make in your code or runtime environment breaks your timing assumptions.

This test framework addresses not only the validation aspect of testing but performance and regression as well.

In a normal situation, the developer creates a {@link javolution.testing.TestSuite TestSuite} which is basically a collection of {@link javolution.testing.TestCase TestCase} logically grouped together. (Note: You will find examples of test suites in the javolution.* source directory). Then by running within an appropriate {@link javolution.testing.TestContext TestContext}, the developer can focus on any particular aspect of interest (behavior, performance, memory usage, ...) For example:[code] // Default tests execution, simple validation and logging of the results. new MyTestSuite().run(); // Specialized context measuring execution time (default average time, with minimum time in parenthesis). TimeContext.enter(); try { new MyTestSuite().run(); } finally { TimeContext.exit(); } // Regression tests (no output, AssertionException raised if any test fails). TestContext.enter(TestContext.REGRESSION); // Or TimeContext.REGRESSION for performance regression test. try { new MyTestSuite().run(); } finally { TestContext.exit(); } [/code] Logging/tests contexts do not have to output the results in a text form. Implementations may store results in databases, spreadsheets or show them graphically. For example:[code] // Logs output to console. LogContext.enter(LogContext.CONSOLE); try { new MyTestSuite().run(); } finally { LogContext.exit(); }[/code]

javolution.text

Provides classes and interfaces to handle text.

FAQ:

  1. Is parsing/formatting of floating-points numbers (e.g. double) equivalent to standard String/Double methods?

    With Javolution 4.1, double formatting/parsing is lossless and functionally the same as with the standard library. Parsing a character sequence will always result in the same number whether it is performed with {@link javolution.text.TypeFormat TypeFormat} or using Double.parseDouble(String)). When formatting a double number, the number of digits output is adjustable. The default (if the number of digits is unspecified) is 17 or 16 when the the 16 digits representation can be parsed back to the same double (mimic the standard library formatting).

    Javolution parsing/formatting do not generate garbage and has no adverse effect on GC. Better, it does not force the user to create intermediate String objects, any CharSequence/Appendable can be used! Serial parsing is also supported (cursor parameter).

  2. I'm accumulating a large string, and all I want to do is append to the end of the current string, which is the better class to use, Text or TextBuilder? Bearing in mind that speed is important, but I also want to conserve memory.

    It all depends of the size of the text to append (the actual size of the document being appended has almost no impact in both cases).

    If you append one character at a time or a small text then {@link javolution.text.TextBuilder#append(Object) TextBuilder.append(Object)} is faster (the cost of copying the characters to the internal buffer is then negligeable and TextBuilder never resizes its internal arrays).

    If you append larger character sequences (the threshold might be around 20 characters) then {@link javolution.text.Text#concat(Text) Text.concat(Text)} is more efficient (it avoid character copies, but creates small nodes objects instead).

  3. In our project's use of strings, there are a lot of instances of directory path names, such as "/proj/lodecase/src/com/lodecase/util/foo.java", and "/proj/lodecase/src/com/lodecase/util/bar.java". Can the 'Text' class save us memory when strings have common prefixes?

    It depends how you build your text. For example in following code:[code] Text directoryName = Text.valueOf("/proj/lodecase/src/com/lodecase/util/"); Text fooFileName = directoryName.plus("foo.java"); Text barFileName = directoryName.plus("bar.java");[/code] The prefix (directoryName)is shared between fooFileName and barFileName.

    Text is a binary tree of blocks of characters. In the example, above, fooFileName is a node with directoryName for head and "foo.java" for tail. The tree is maintained balanced automatically through tree rotations.

javolution.util

Provides high-performance collection classes and miscellaneous utilities; although this package provides very few collection classes, they are substitutes for most of java.util.* classes (for example, java.util.IdentityHashMap would be a {@link javolution.util.FastMap FastMap} with an {@link javolution.util.FastComparator#IDENTITY identity} key comparator).

Overview:

Javolution collections are compliant with standard collections (generic when built with the ant target 1.5) and they can safely be used with RTSJ virtual machines (e.g. if the capacity of a collection increases, the extension part is allocated from the same memory area as the collection itself).

They support direct iterations with the following advantages:

  • Faster than iterators, see benchmark.
  • No object creation not even the iterator object itself. For example, visiting a tree structure using iterators creates as many iterators as they are nodes in the tree:[code] public static void visit(Collection node) { for (Collection i : node) { // Creates iterator. visit(i); } }[/code] Not so with direct iterations:[code] public static void visit(FastCollection node) { for (FastCollection.Record r = node.head(), end = node.tail(); (r = r.getNext()) != end;) { visit(node.valueOf(r)); } }[/code]
  • Used to implement most of {@link javolution.util.FastCollection FastCollection} base class methods (including {@link javolution.util.FastCollection#iterator iterator()}).
  • Support forward/backward iterations from the start (head) or from the end (tail)
  • Thread-safe as long as objects are not inserted/removed during iterations. Objects can safely be append/prepend by the current thread or other threads. (Note: {@link javolution.util.FastMap#setShared Shared FastMap} are always thread-safe even when entries are removed).
  • Fully integrated with the JDK1.5+ generic framework (strong typing) and still compatible with other platforms (J2ME, 1.4, GCJ).
Here are few examples of direct iterations:[code] FastList list; for (FastList.Node n = list.head(), end = list.tail(); (n = n.getNext()) != end;) { String value = n.getValue(); // No typecast necessary. } ... FastMap map; for (FastMap.Entry e = map.head(), end = map.tail(); (e = e.getNext()) != end;) { String key = e.getKey(); // No typecast necessary. Thread value = e.getValue(); // No typecast necessary. }[/code]

Users may provide a read-only view of any {@link javolution.util.FastCollection FastCollection} (or {@link javolution.util.FastMap FastMap}) instance using the {@link javolution.util.FastCollection#unmodifiable() FastCollection.unmodifiable()} (or {@link javolution.util.FastMap#unmodifiable FastMap.unmodifiable()}) method. For example:[code] public class Polynomial { private final FastSet _terms = new FastSet(); // Read-only view (also thread-safe as terms are not "deleted"). public Set getTerms() { return _terms.unmodifiable(); } }[/code]

Collection/maps of primitive types can be created using the {@link javolution.util.Index Index} class. It avoids the overhead of wrapping primitives types (for reasonably small int values). For example:[code] public class SparseVector { FastMap _elements = new FastMap(); ... }[/code]

Although all collections capacity increases smoothly (no resizing/copy or rehashing ever performed), it is nevertheless possible to specify an initial capacity; in which case, all necessary storage is allocated at creation. For RTSJ VMs, all collections/maps can reside in ImmortalMemory (e.g. static) and be used by all threads (including NoHeapRealtimeThread) without resulting into memory leaks or illegal access errors. For example:[code] public class XmlFormat { // RTSJ Unsafe! Memory leaks (when entries removed) or IllegalAssignmentError (when new entries while in ScopedArea). static HashMap ClassToFormat = HashMap(); // RTSJ Safe! Removed entries are internally recycled, new entries are in ImmortalMemory. static FastMap ClassToFormat = FastMap(); }[/code] For more details, please read Javolution-Collection.pdf

.

Temporary collection classes can be recycled (e.g. throw-away collections) to avoid the creation cost. For example:[code] static void removeDuplicate(List persons) { FastSet tmp = FastSet.newInstance(); // Possibly recycled instance. tmp.addAll(persons); persons.clear(); persons.addAll(tmp); FastSet.recycle(tmp); // Recycles the temporary instance. }[/code]

Here is a summary of the collection classes with their defining characteristics:
Javolution Collections Classes
Ordering Duplication Allowed Custom Comparators Record Type Miscellaneous
{@link javolution.util.FastTable FastTable} Insertion Order Yes {@link javolution.util.FastTable#setValueComparator setValueComparator(FastComparator)} {@link javolution.util.Index Index} Thread-safe random access collection
No array resize/copy ever performed
{@link javolution.util.FastList FastList} Insertion Order Yes {@link javolution.util.FastList#setValueComparator setValueComparator(FastComparator)} {@link javolution.util.FastList.Node Node} Recycle their own nodes (no adverse effect on GC)
{@link javolution.util.FastSet FastSet} Insertion Order No {@link javolution.util.FastSet#setValueComparator setValueComparator(FastComparator)} {@link javolution.util.FastCollection.Record Record} Based on {@link javolution.util.FastSet FastMap} (same characteristics)
FastTree Comparator No setValueComparator(FastComparator) TreeNode (not implemented)
{@link javolution.util.FastMap FastMap} Insertion Order Key: No
Value: Yes
{@link javolution.util.FastMap#setKeyComparator setKeyComparator(FastComparator)}
{@link javolution.util.FastMap#setValueComparator setValueComparator(FastComparator)}
{@link javolution.util.FastMap.Entry Entry} Thread-safe when marked as {@link javolution.util.FastMap#setShared shared}
No rehash/resize ever performed
Recycle their own entries (no adverse effect on GC)

FAQ:

  1. ArrayList may throw ConcurrentModificationException, but Javolution FastTable does not, why?

    FastTable (or any Javolution collection/map) do support concurrent modifications as long as these are not insertions at an arbitrary position or deletions (Note: Shared FastMap does support concurrent deletions). In other words you can safely iterate (using iterators or not) through a FastList, FastMap (entries, keys values), FastTable, etc. while new elements/entries are being added (by you or another thread). You can also export a {@link javolution.util.FastCollection#unmodifiable() read-only} view over your collection and still add more elements to it.

    Disallowing concurrent modifications (standard java util) has proven to be a performance killer for many (forcing users to work with copies of their whole collections). Furthermore the additional checks required directly impact performance (e.g. ArrayList iterations about 3x slower than FastTable iterations).

  2. Do you have a test case showing any scenario of concurrent modification where ArrayList "fails" and FastTable doesn't?

    Let's say that you have a collection of "Units", and you want to provide users with a read-only view of these units. The following code will fail miserably:[code] public class Unit { static ArrayList INSTANCES = new ArrayList(); public static List getInstances() { return Collections.unmodifiableList(INSTANCES); } }[/code] Why? Because, it the user iterates on the read-only list of units while a new unit is added to the collection (by another thread) a ConcurrentModificationException is automatically raised. In other words, it is almost impossible to provide a "read-only" view of non-fixed size collections with the current java.util classes (e.g. you will have to replace the whole collection each time a new unit is added).

    Now with FastTable the following is completely safe even when new units are added:[code] public class Unit { static FastTable INSTANCES = new FastTable(); public static List getInstances() { return INSTANCES.unmodifiable(); } }[/code]

  3. Do checks for concurrent modifications make your code safer?

    Not really. The current checks for concurrent modifications do not "guarantee" that concurrent modifications will not occur! You can imagine two threads one updating a collection and the other one iterating the collection. As long as the update is not performed while the other thread is iterating, everything is fine (no ConcurrentModificationException)! But, if for a reason or another the timing changes (e.g. in the user environment) and iterations are performed at the wrong time then your application crashes... Not a good thing and very high probability for this to happen!

  4. Are {@link javolution.util.FastMap#setShared shared maps} valid substitutes for ConcurrentHashMap?

    Unlike ConcurrentHashMap access to a shared FastMap never blocks. Retrieval reflects the map state not older than the last time the accessing threads have been synchronized* (for multi-processors systems synchronizing ensures that the CPU internal cache is not stale).

    In practice, it means that most well-written concurrent programs should be able to use shared FastMap in place of ConcurrentHashMap as threads are already synchronized to ensure proper behavior.

    * It is important for both threads to synchronize on the same monitor in order to set up the happens-before relationship properly. It is not the case that everything visible to thread A when it synchronizes on object X becomes visible to thread B after it synchronizes on object Y. The release and acquire have to "match" (i.e., be performed on the same monitor) to have the right semantics. Otherwise, the code has a data race.

  5. Are all Javolution collection thread-safe?

    Collections/Maps are thread-safe with regard to access (no need to synchronize reading even if the collection is modified concurrently). But the modifications themselves require either the collection/map to be marked shared or synchronization to be used.

  6. What is the overhead in term of performance when FastMap.setShared is set to true?

    Marking the map shared avoid synchronizing when possible (e.g. put when entry already exists or remove when entry does not exist), if a new entry is created and added, synchronization is performed internally. In all cases there is no impact on reading (never synchronized).

javolution.xml

Provides support for the encoding of objects, and the objects reachable from them, into XML; and the complementary reconstruction of the object graph from XML.

XML marshalling/unmarshalling facility:

XML Data Binding

Key Advantages:

  • Real-time characteristics with no adverse effect on memory footprint or garbage collection (e.g. it can be used for time critical communications). {@link javolution.xml.XMLFormat XMLFormat} is basically a "smart" wrapper around our real-time StAX-like {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter}.
  • Works directly with your existing Java classes, no need to create new classes or customize your implementation in any way.
  • The XML representation can be high level and impervious to obfuscation or changes to your implementation.
  • Performance on a par or better than default JavaTM Serialization/Deserialization (See bindmark for performance comparison).
  • Runs on any platform including J2ME CLDC 1.0 It does not require reflection or or any interface (e.g. Serializable) to be implemented.
  • The XML mapping can be defined for a top class (or interface) and is automatically inherited by all sub-classes (or all implementing classes).
  • Supports object references (to avoid expanding objects already formatted).

The default XML mapping for a class and its sub-classes is typically defined using a static final {@link javolution.xml.XMLFormat XMLFormat} instance. For example:[code] public abstract class Graphic implements XMLSerializable { private boolean _isVisible; private Paint _paint; // null if none. private Stroke _stroke; // null if none. private Transform _transform; // null if none. // Default XML format with name associations (members identified by an unique name). // See XMLFormat for examples of positional associations. protected static final XMLFormat XML = new XMLFormat(Graphic.class) { public void write(Graphic g, OutputElement xml) throws XMLStreamException { xml.setAttribute("isVisible", g._isVisible); xml.add(g._paint, "Paint"); xml.add(g._stroke, "Stroke"); xml.add(g._transform, "Transform"); } public void read(InputElement xml, Graphic g) throws XMLStreamException { g._isVisible = xml.getAttribute("isVisible", true); g._paint = xml.get("Paint"); g._stroke = xml.get("Stroke"); g._transform = xml.get("Transform"); } }; }[/code] Sub-classes may override the inherited XML format:[code] public class Area extends Graphic { private Shape _geometry; // Adds geometry to format. protected static final XMLFormat XML = new XMLFormat(Area.class) { public void write(Area area, OutputElement xml) throws XMLStreamException { Graphic.XML.write(area, xml); // Calls parent write. xml.add(area._geometry, "Geometry"); } public void read(InputElement xml, Area area) throws XMLStreamException { Graphic.XML.read(xml, area); // Calls parent read. area._geometry = xml.get("Geometry"); } }; }[/code] The following writes a graphic area to a file, then reads it:[code] // Creates some useful aliases for class names. XMLBinding binding = new XMLBinding(); binding.setAlias(Color.class, "Color"); binding.setAlias(Polygon.class, "Polygon"); binding.setClassAttribute("type"); // Use "type" instead of "class" for class attribute. // Writes the area to a file. XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream("C:/area.xml")); writer.setBinding(binding); // Optional. writer.setIndentation("\t"); // Optional (use tabulation for indentation). writer.write(area, "Area", Area.class); writer.close(); // Reads the area back XMLObjectReader reader = XMLObjectReader.newInstance(new FileInputStream("C:/area.xml")); reader.setBinding(binding); Area a = reader.read("Area", Area.class); reader.close(); [/code] Here is an example of valid XML representation for an area:[code] [/code]

The following table illustrates the variety of XML representations supported (Foo class with a single String member named text):

XML FORMAT XML DATA
[code]XMLFormat XML = new XMLFormat(Foo.class) { public void write(Foo foo, OutputElement xml) throws XMLStreamException { xml.setAttribute("text", foo.text); } public void read(InputElement xml, Foo foo) throws XMLStreamException { foo.text = xml.getAttribute("text", ""); } };[/code]
 <!-- Member as attribute -->
 <Foo text="This is a text"/>
[code]XMLFormat XML = new XMLFormat(Foo.class) { public void write(Foo foo, OutputElement xml) throws XMLStreamException { xml.add(foo.text); } public void read(InputElement xml, Foo foo) throws XMLStreamException { foo.text = xml.getNext(); } };[/code]
 <!-- Member as anonymous nested element -->
 <Foo>
     <java.lang.String value="This is a text"/>
 </Foo>
[code]XMLFormat XML = new XMLFormat(Foo.class) { public void write(Foo foo, OutputElement xml) throws XMLStreamException { xml.addText(foo.text); // or xml.getStreamWriter().writeCDATA(foo.text) to use CDATA block. } public void read(InputElement xml, Foo foo) throws XMLStreamException { foo.text = xml.getText().toString(); // Content of a text-only element. } };[/code]
 <!-- Member as Character Data -->
 <Foo>This is a text</Foo>
[code]XMLFormat XML = new XMLFormat(Foo.class) { public void write(Foo foo, OutputElement xml) throws XMLStreamException { xml.add(foo.text, "Text"); } public void read(InputElement xml, Foo foo) throws XMLStreamException { foo.text = xml.get("Text"); } };[/code]
 <!-- Member as named element of unknown type  -->
 <Foo>
     <Text class="java.lang.String" value="This is a text"/>
 </Foo>
[code]XMLFormat XML = new XMLFormat(Foo.class) { public void write(Foo foo, OutputElement xml) throws XMLStreamException { xml.add(foo.text, "Text", String.class); } public void read(InputElement xml, Foo foo) throws XMLStreamException { foo.text = xml.get("Text", String.class); } };[/code]
 <!-- Member as named element of actual type known -->
 <Foo>
     <Text value="This is a text"/>
 </Foo>

The {@link javolution.xml.XMLFormat XMLFormat} does not have to use the class public no-arg constructor, instances can be created using factory methods, private constructors (with constructor parameters set from the XML element) or even retrieved from a collection (if the object is shared or unique). For example:[code] public final class Point implements XMLSerializable { // Default XMLFormat can be private as the class cannot be extended. static final XMLFormat XML = new XMLFormat(Point.class) { public boolean isReferencable() { return false; // Always manipulates by value. } public Point newInstance(Class cls, InputElement xml) throws XMLStreamException { return Point.valueOf(xml.getAttribute("x", 0), xml.getAttribute("y", 0)); } public void write(Point point, OutputElement xml) throws XMLStreamException { xml.setAttribute("x", point._x); xml.setAttribute("y", point._y); } public void read(InputElement xml, Point point) throws XMLStreamException { // Do nothing immutable. } }; private int _x; private int _y; private Point() {}; // No-arg constructor not visible. public static Point valueOf(int x, int y) { ... } }[/code]

Document cross-references are supported, including circular references. Let's take for example:[code] public class Polygon implements Shape, XMLSerializable { private Point[] _vertices; static final XMLFormat XML = new XMLFormat(Polygon.class) { public void write(Polygon polygon, OutputElement xml) throws XMLStreamException { xml.setAttibutes("count", _vertices.length); for (int i=0; i < _vertices.length; i++) { xml.add(_vertices[i], "Vertex", Point.class); } } public void read(InputElement xml, Polygon polygon) throws XMLStreamException { int count = xml.getAttributes("count", 0); polygon._vertices = new Point[count]; for (int i=0; i < count; i++) { _vertices[i] = xml.get("Vertex", Point.class); } } }; } Polygon[] polygons = new Polygon[] {p1, p2, p1}; ... TextBuilder xml = TextBuilder.newInstance(); AppendableWriter out = new AppendableWriter().setOutput(xml) XMLObjectWriter writer = XMLObjectWriter.newInstance(out); writer.setXMLReferenceResolver(new XMLReferenceResolver()); // Enables cross-references. writer.write(polygons, "Polygons", Polygon[].class); writer.close(); System.out.println(xml); [/code] Prints the following (noticed that the first polygon and last one are being shared).[code] [/code]

ALGORITHMS:

Our {@link javolution.xml.XMLObjectReader XMLObjectReader}/{@link javolution.xml.XMLObjectWriter XMLObjectWriter} are in fact simple wrappers around our Javolution high-performance StAX-like {@link javolution.xml.stream.XMLStreamReader XMLStreamReader} and {@link javolution.xml.stream.XMLStreamWriter XMLStreamWriter} classes. The logic of these wrappers is described below:

Marshalling:

Input: object, referenceResolver, binding
Output: outputElement 

1. class = object.getClass()
    
2. outputElement.getStreamWriter().writeStartElement(name/uri)

   The new element name/uri is:
   
      a - Specified by caller, e.g. add(object, name, uri, class) 
          If the class is not specified e.g. add(object, name, uri) a class attribute is written.
                    
      b - binding.getLocalName(class)/binding.getURI(class), e.g add(object)

3. isReference = referenceResolver.writeReference(object, outputElement)
   
4. if (!isReference) binding.getFormat(class).write(object, outputElement)

5. outputElement.getStreamWriter().writeEndElement()

6. end


Unmarshalling:

Input: inputElement, referenceResolver, binding
Output: object

1. object = referenceResolver.readReference(inputElement)
   
2. if (object != null) Goto 8 // Found reference

3. class is either:

    a - Specified by caller, e.g. get("name", class)
    
    b - binding.getClass(class attribute value)
    
    c - binding.getClass(element name, element uri)

4. format = binding.getFormat(class)

5. object = format.newInstance(class, inputElement)

6. referenceResolver.createReference(object, inputElement) // Done before parsing to support circular references.

7. format.read(inputElement, object)

8. inputElement.getStreamReader().nextTag()

9. end

javolution.xml.sax

Provides {@link javolution.xml.sax.SAX2ReaderImpl SAX2} and {@link javolution.xml.sax.XMLReaderImpl SAX2-Like} parsers; the later being several times faster than conventional SAX2 parsers (by avoiding String allocations while parsing).

javolution.xml.stream

Provides StAX-like XML readers/writers which do not require object creation (such as String) and are consequently faster and more time predictable than standard StAX classes.

The main difference with "javax.xml.stream.*" classes is the use of CharSequence instead of String. Since String is a CharSequence (JDK 1.4+), most existing StAX code requires very little modification to be used with these new classes.

For more information about the usage of this package please read the documentation for the {@link javolution.xml.stream.XMLStreamReader} and {@link javolution.xml.stream.XMLStreamWriter} interfaces.

For more information about StAX (Streaming API for XML) in general see Wikipedia: StAX

javolution.xml.ws

Provides classes and interfaces to create and handle web services.

At this stage, only a simple base web service client is provided. Future releases may include more advanced clients (e.g. parsing WSDL files), classes to easily create web service server, etc.

org.xml.sax

This package provides the core SAX APIs. Some SAX1 APIs are deprecated to encourage integration of namespace-awareness into designs of new applications and into maintenance of existing infrastructure.

See http://www.saxproject.org for more information about SAX.

SAX2 Standard Feature Flags

One of the essential characteristics of SAX2 is that it added feature flags which can be used to examine and perhaps modify parser modes, in particular modes such as validation. Since features are identified by (absolute) URIs, anyone can define such features. Currently defined standard feature URIs have the prefix http://xml.org/sax/features/ before an identifier such as validation. Turn features on or off using setFeature. Those standard identifiers are:

Feature ID Access Default Description
external-general-entities read/write unspecified Reports whether this parser processes external general entities; always true if validating.
external-parameter-entities read/write unspecified Reports whether this parser processes external parameter entities; always true if validating.
is-standalone (parsing) read-only, (not parsing) none not applicable May be examined only during a parse, after the startDocument() callback has been completed; read-only. The value is true if the document specified standalone="yes" in its XML declaration, and otherwise is false.
lexical-handler/parameter-entities read/write unspecified A value of "true" indicates that the LexicalHandler will report the beginning and end of parameter entities.
namespaces read/write true A value of "true" indicates namespace URIs and unprefixed local names for element and attribute names will be available.
namespace-prefixes read/write false A value of "true" indicates that XML qualified names (with prefixes) and attributes (including xmlns* attributes) will be available.
resolve-dtd-uris read/write true A value of "true" indicates that system IDs in declarations will be absolutized (relative to their base URIs) before reporting. (That is the default behavior for all SAX2 XML parsers.) A value of "false" indicates those IDs will not be absolutized; parsers will provide the base URI from Locator.getSystemId(). This applies to system IDs passed in
  • DTDHandler.notationDecl(),
  • DTDHandler.unparsedEntityDecl(), and
  • DeclHandler.externalEntityDecl().
It does not apply to EntityResolver.resolveEntity(), which is not used to report declarations, or to LexicalHandler.startDTD(), which already provides the non-absolutized URI.
string-interning read/write unspecified Has a value of "true" if all XML names (for elements, prefixes, attributes, entities, notations, and local names), as well as Namespace URIs, will have been interned using j2me.lang.String.intern. This supports fast testing of equality/inequality against string constants, rather than forcing slower calls to String.equals().
unicode-normalization-checking read/write false Controls whether the parser reports Unicode normalization errors as described in section 2.13 and Appendix B of the XML 1.1 Recommendation. If true, Unicode normalization errors are reported using the ErrorHandler.error() callback. Such errors are not fatal in themselves (though, obviously, other Unicode-related encoding errors may be).
use-attributes2 read-only not applicable Returns "true" if the Attributes objects passed by this parser in ContentHandler.startElement() implement the org.xml.sax.ext.Attributes2 interface. That interface exposes additional DTD-related information, such as whether the attribute was specified in the source text rather than defaulted.
use-locator2 read-only not applicable Returns "true" if the Locator objects passed by this parser in ContentHandler.setDocumentLocator() implement the org.xml.sax.ext.Locator2 interface. That interface exposes additional entity information, such as the character encoding and XML version used.
use-entity-resolver2 read/write true Returns "true" if, when setEntityResolver is given an object implementing the org.xml.sax.ext.EntityResolver2 interface, those new methods will be used. Returns "false" to indicate that those methods will not be used.
validation read/write unspecified Controls whether the parser is reporting all validity errors; if true, all external entities will be read.
xmlns-uris read/write false Controls whether, when the namespace-prefixes feature is set, the parser treats namespace declaration attributes as being in the http://www.w3.org/2000/xmlns/ namespace. By default, SAX2 conforms to the original "Namespaces in XML" Recommendation, which explicitly states that such attributes are not in any namespace. Setting this optional flag to "true" makes the SAX2 events conform to a later backwards-incompatible revision of that recommendation, placing those attributes in a namespace.
xml-1.1 read-only not applicable Returns "true" if the parser supports both XML 1.1 and XML 1.0. Returns "false" if the parser supports only XML 1.0.

Support for the default values of the namespaces and namespace-prefixes properties is required. Support for any other feature flags is entirely optional.

For default values not specified by SAX2, each XMLReader implementation specifies its default, or may choose not to expose the feature flag. Unless otherwise specified here, implementations may support changing current values of these standard feature flags, but not while parsing.

SAX2 Standard Handler and Property IDs

For parser interface characteristics that are described as objects, a separate namespace is defined. The objects in this namespace are again identified by URI, and the standard property URIs have the prefix http://xml.org/sax/properties/ before an identifier such as lexical-handler or dom-node. Manage those properties using setProperty(). Those identifiers are:

Property ID Description
declaration-handler Used to see most DTD declarations except those treated as lexical ("document element name is ...") or which are mandatory for all SAX parsers (DTDHandler). The Object must implement org.xml.sax.ext.DeclHandler.
document-xml-version May be examined only during a parse, after the startDocument() callback has been completed; read-only. This property is a literal string describing the actual XML version of the document, such as "1.0" or "1.1".
dom-node For "DOM Walker" style parsers, which ignore their parser.parse() parameters, this is used to specify the DOM (sub)tree being walked by the parser. The Object must implement the org.w3c.dom.Node interface.
lexical-handler Used to see some syntax events that are essential in some applications: comments, CDATA delimiters, selected general entity inclusions, and the start and end of the DTD (and declaration of document element name). The Object must implement org.xml.sax.ext.LexicalHandler.
xml-string Readable only during a parser callback, this exposes a TBS chunk of characters responsible for the current event.

All of these standard properties are optional; XMLReader implementations need not support them.

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.