001 package xmlBeans.cursor;
002
003 import com.bea.xml.XmlCursor;
004 import org.openuri.bea.samples.workshop.xmlBeans.mixedContent.DescriptionType;
005 import org.openuri.bea.samples.workshop.xmlBeans.mixedContent.InventoryDocument;
006 import org.openuri.bea.samples.workshop.xmlBeans.mixedContent.InventoryDocument.Inventory;
007 import org.openuri.bea.samples.workshop.xmlBeans.mixedContent.ItemType;
008
009 /**
010 * A web service illustrating how you can use an XML cursor
011 * to manipulate the content of an element. While working with
012 * strongly-typed XML (in which you are accessing the XML
013 * through an API generated from schema) provides easy
014 * access for getting and setting the entire value of an
015 * element or attribute, it does not easily provide finer
016 * grained access to an element's content. This web service
017 * shows how you can use an XML cursor to "dive into" an
018 * element's content, manipulating it on a character-by-
019 * character level. <br/><br/>
020 *
021 * The code in this web service is designed to look at the
022 * description of each item in an inventory list, creating
023 * a link wherever the description contains a reference
024 * to another item in the inventory list. This alters the
025 * description element so that it contains a mix of text and
026 * link elements. Such an element is said to have "mixed
027 * content."
028 *
029 * @common:target-namespace namespace="http://workshop.bea.com/MixedContent"
030 */
031 public class MixedContent implements com.bea.jws.WebService
032 {
033 /**
034 * Creates links between items in an inventory list by inserting
035 * a <link> element for each linked item. An XmlCursor
036 * instance passes through each <description> element, looking
037 * for text matching the name of an item. <br/><br/>
038 *
039 * To test this method, paste the contents of the
040 * InventoryItem.xml file over the <inventory>
041 * element (and its children) provided in by Test View.
042 * Click linkItems to view the XML produced by this code.
043 *
044 * @common:operation
045 */
046 public InventoryDocument linkItems(InventoryDocument inventoryDoc)
047 {
048 /**
049 * Retrieve the inventory element and get an array of
050 * the item elements it contains.
051 */
052 Inventory inventory = inventoryDoc.getInventory();
053 ItemType[] items = inventory.getItemArray();
054
055 /**
056 * Loop through the item elements, examining the
057 * description for each to see if another inventory item
058 * is mentioned.
059 */
060 for (int i = 0; i < items.length; i++)
061 {
062 /**
063 * Get details about the current item, including
064 * its length. This will be used to measure text
065 * while exploring the description.
066 */
067 String itemName = items[i].getName();
068 String itemId = new Integer(items[i].getId()).toString();
069 int itemCharCount = itemName.length();
070
071 /**
072 * Loop through the item descriptions, looking at each
073 * for the name of the current item.
074 */
075 for (int j = 0; j < items.length; j++)
076 {
077 DescriptionType description = items[j].getDescription();
078
079 /**
080 * Insert an XmlCursor instance and set it at
081 * the beginning of the description element's text,
082 * just after the start tag.
083 */
084 XmlCursor cursor = description.newCursor();
085 cursor.toLastAttribute();
086 cursor.toNextToken();
087
088 /**
089 * Get a String containing the characters to the
090 * immediate right of the cursor, up to the next
091 * token (in this case, the next element after
092 * the description element). Get the number of
093 * characters to the right of the cursor; this will
094 * be used to mark the distance the cursor should move
095 * before trying another item's description. Also,
096 * create a charCount variable to mark the cursor's
097 * current position.
098 */
099 String cursorChars = cursor.getChars();
100 int descCharCount = cursorChars.length();
101 int charCount = 0;
102
103 /**
104 * As long at the cursor hasn't reached the end of the
105 * description text, check to see if the text to the
106 * cursor's immediate right matches the item name sought.
107 * If it does match, remove the text and create a link
108 * element to replace it.
109 */
110 while (charCount < descCharCount)
111 {
112 /**
113 * A char array to hold the characters currently being
114 * checked.
115 */
116 char[] chars = new char[itemCharCount];
117
118 /**
119 * Pass the char array with the getChars method. This
120 * method will find the chars from the cursor's
121 * immediate right to the char at itemCharCount (the
122 * length of the item name currently sought). The
123 * method's second argument indicates where in the char
124 * array the found text should begin -- here, at the
125 * beginning.
126 */
127 int charsReturned = cursor.getChars(chars, 0, itemCharCount);
128
129 /**
130 * If the characters in chars match the item name, then
131 * make a link from the text.
132 */
133 if (new String(chars).equals(itemName))
134 {
135 /**
136 * Remove the found item name.
137 */
138 cursor.removeChars(itemCharCount);
139 /**
140 * Begin a new link element whose namespace is the
141 * same as the rest of the inventory document. The
142 * beginElement method essentially creates a new
143 * element with the name specified around the current
144 * cursor.
145 */
146 cursor.beginElement("link",
147 "http://openuri.org/bea/samples/workshop/xmlBeans/mixedContent");
148 /**
149 * Insert an id attribute and make its value the id of
150 * the item sought.
151 */
152 cursor.insertAttributeWithValue("id", itemId);
153 /**
154 * Insert the item name as the element's value.
155 */
156 cursor.insertChars(itemName);
157 }
158 /**
159 * Move on to the next character in the description.
160 */
161 cursor.toNextChar(1);
162 /**
163 * Increment the counter tracking the cursor's position.
164 */
165 charCount++;
166 }
167 /**
168 * Be sure to dispose of a cursor that's no longer needed.
169 * This allows it to be garbage collected.
170 */
171 cursor.dispose();
172 }
173 }
174 /**
175 * Return the edited document.
176 */
177 return inventoryDoc;
178 }
179 }
|