| /* Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.xmlbeans.samples.enumeration; |
| |
| import org.apache.xmlbeans.XmlError; |
| import org.apache.xmlbeans.XmlException; |
| import org.apache.xmlbeans.XmlObject; |
| import org.apache.xmlbeans.XmlOptions; |
| import org.apache.xmlbeans.samples.enumeration.schemaenum.easypo.LineItem; |
| import org.apache.xmlbeans.samples.enumeration.schemaenum.easypo.PurchaseOrderDocument; |
| import org.apache.xmlbeans.samples.enumeration.schemaenum.pricesummary.ItemType; |
| import org.apache.xmlbeans.samples.enumeration.schemaenum.pricesummary.PriceSummaryDocument; |
| import org.apache.xmlbeans.samples.enumeration.schemaenum.pricesummary.PriceType; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| |
| /** |
| * This sample illustrates how you can access XML values that are |
| * defined in schema as enumerations. When a schema containing |
| * enumerations is compiled, the generated Java types represent the |
| * schema enumerations with Java enumerations. You can access these through |
| * their constants and corresponding int values. |
| * <p/> |
| * The schemas used by this sample are defined in PriceSummary.xsd and |
| * EasyPO.xsd. |
| */ |
| public class SchemaEnum |
| { |
| /** |
| * Receives an PO XML instance and uses its data to create an XML |
| * document based another schema, and which summarizes the items |
| * in the PO by price. |
| * |
| * @param args An array containing one argument: the path to an XML instance |
| * conforming to the schema in EasyPO.xsd. |
| */ |
| public static void main(String[] args) |
| { |
| // Create an instance of this class to work with. |
| SchemaEnum thisSample = new SchemaEnum(); |
| |
| // Create an instance of a type based on the received XML's schema |
| // and use it to print what the sample received. |
| PurchaseOrderDocument poDoc = thisSample.parseXml(args[0]); |
| System.out.println("Received XML: \n\n" + poDoc.toString()); |
| |
| // Print the summarized items in XML based on a different schema. |
| PriceSummaryDocument summaryDoc = thisSample.summarizeItems(poDoc); |
| System.out.println("Summarized items: \n\n" + summaryDoc.toString()); |
| |
| // Print a simple non-XML list of items by threshold. |
| String sortedItems = thisSample.sortByThreshold(summaryDoc); |
| System.out.println("Sorted items: \n" + sortedItems); |
| |
| // Validate the result. |
| System.out.println("New XML is valid: " + |
| thisSample.validateXml(summaryDoc)); |
| } |
| |
| /** |
| * <p>This method uses values in the incoming XML to construct |
| * a new XML document of a different schema. PriceSummary.xsd, the schema |
| * for the new document, defines XML enumerations for a price |
| * threshold attribute. Items whose price is between $10 and $20 receive |
| * a threshold value of "Between10And20Dollars"; items above 20 get a threshold |
| * value of "Above20Dollars".</p> |
| * <p/> |
| * <p>This method loops through the purchase order items, creating a summary |
| * document that specifies their threshold value.</p> |
| * <p/> |
| * <p>You can verify this method's work by comparing the resulting XML with |
| * the XML in PriceSummary.xml. You can also use this method's return value |
| * to test the sortByThreshold method.</p> |
| */ |
| public PriceSummaryDocument summarizeItems(PurchaseOrderDocument poDoc) |
| { |
| PurchaseOrderDocument.PurchaseOrder po = poDoc.getPurchaseOrder(); |
| |
| // Create a new instance of the PriceSummary schema. This is the document |
| // the code creates, extracting values from the purchase order. |
| PriceSummaryDocument summaryDoc = PriceSummaryDocument.Factory.newInstance(); |
| PriceSummaryDocument.PriceSummary summary = summaryDoc.addNewPriceSummary(); |
| |
| // Create <price> elements to hold <item> elements according to their |
| // price threshold. |
| PriceType priceZero = summary.addNewPrice(); |
| PriceType priceTen = summary.addNewPrice(); |
| PriceType priceTwenty = summary.addNewPrice(); |
| |
| // Set the threshold attribute value for the two new elements. |
| priceZero.setThreshold(PriceType.Threshold.BELOW_10_DOLLARS); |
| priceTen.setThreshold(PriceType.Threshold.BETWEEN_10_AND_20_DOLLARS); |
| priceTwenty.setThreshold(PriceType.Threshold.ABOVE_20_DOLLARS); |
| |
| // Loop through the purchase order <line-item> elements. If their |
| // <price> child element is between 10.00 and 20.00, add the <line-item> |
| // to the <price> element whose threshold is 10.00. For those over 20.00, |
| // add them to the <price> element whose threshold is 20.00. |
| |
| // There don't happen to be any under 10.00, but handle this case anyway. |
| LineItem[] items = po.getLineItemArray(); |
| for (int i = 0; i < items.length; i++) |
| { |
| LineItem item = items[i]; |
| |
| if (item.getPrice() < 10.00) |
| { |
| |
| ItemType newItem = priceZero.addNewItem(); |
| newItem.setTitle(item.getDescription()); |
| newItem.xsetQuantity(item.xgetQuantity()); |
| newItem.setAmount(item.getPrice()); |
| |
| } else if (item.getPrice() >= 10.00 && item.getPrice() < 20.00) |
| { |
| |
| ItemType newItem = priceTen.addNewItem(); |
| newItem.setTitle(item.getDescription()); |
| newItem.xsetQuantity(item.xgetQuantity()); |
| newItem.setAmount(item.getPrice()); |
| |
| } else if (item.getPrice() >= 20.00) |
| { |
| |
| ItemType newItem = priceTwenty.addNewItem(); |
| newItem.setTitle(item.getDescription()); |
| newItem.xsetQuantity(item.xgetQuantity()); |
| newItem.setAmount(item.getPrice()); |
| } |
| } |
| return summaryDoc; |
| } |
| |
| /** |
| * <p>This method loops through a price summary XML document to |
| * create a string that lists the items grouped by threshold. |
| * Unlike the summarizeItems method, which creates a new XML |
| * document that contains an attribute whose value is enumerated, |
| * this method retrieves values from an enumeration.</p> |
| * <p/> |
| * <p>This method illustrates how you can use the int value corresponding |
| * to enumerations to specify them in Java switch statements.</p> |
| */ |
| public String sortByThreshold(PriceSummaryDocument summaryDoc) |
| { |
| // Extract the summary element from the incoming XML, then use it |
| // to extract an array of the price elements. |
| PriceSummaryDocument.PriceSummary summary = summaryDoc.getPriceSummary(); |
| PriceType[] priceElements = summary.getPriceArray(); |
| |
| StringBuilder responseBuffer = new StringBuilder(); |
| |
| // Create string buffers to hold the sorted results of the values |
| // retrieved. |
| StringBuilder zeroBuffer = new StringBuilder("\nItems under 10 dollars: \n"); |
| StringBuilder tenBuffer = new StringBuilder("\nItems between 10 and 20 dollars: \n"); |
| StringBuilder twentyBuffer = new StringBuilder("\nItems more than 20 dollars: \n"); |
| |
| // Loop through the price elements, extracting the array of <item> child |
| // elements in each. |
| for (int i = 0; i < priceElements.length; i++) |
| { |
| ItemType[] itemElements = priceElements[i].getItemArray(); |
| |
| // Loop through the <item> elements, discovering which threshold |
| // the item belongs to, then using the element's <title> value |
| // in in a sorted list. |
| for (int j = 0; j < itemElements.length; j++) |
| { |
| ItemType item = itemElements[j]; |
| |
| // For each <item> element, find out the int value of its <price> |
| // parent element's threshold attribute value. Append the item's |
| // title to the appropriate string buffer. |
| switch (priceElements[i].getThreshold().intValue()) |
| { |
| |
| case PriceType.Threshold.INT_BELOW_10_DOLLARS: |
| zeroBuffer.append(" " + item.getTitle() + "\n"); |
| break; |
| |
| case PriceType.Threshold.INT_BETWEEN_10_AND_20_DOLLARS: |
| tenBuffer.append(" " + item.getTitle() + "\n"); |
| break; |
| |
| case PriceType.Threshold.INT_ABOVE_20_DOLLARS: |
| twentyBuffer.append(" " + item.getTitle() + "\n"); |
| break; |
| |
| default: |
| System.out.println("Yo! Something unexpected happened!"); |
| break; |
| } |
| } |
| } |
| responseBuffer.append(tenBuffer); |
| responseBuffer.append(twentyBuffer); |
| return responseBuffer.toString(); |
| } |
| |
| /** |
| * <p>Validates the XML, printing error messages when the XML is invalid. Note |
| * that this method will properly validate any instance of a compiled schema |
| * type because all of these types extend XmlObject.</p> |
| * <p/> |
| * <p>Note that in actual practice, you'll probably want to use an assertion |
| * when validating if you want to ensure that your code doesn't pass along |
| * invalid XML. This sample prints the generated XML whether or not it's |
| * valid so that you can see the result in both cases.</p> |
| * |
| * @param xml The XML to validate. |
| * @return <code>true</code> if the XML is valid; otherwise, <code>false</code> |
| */ |
| public boolean validateXml(XmlObject xml) |
| { |
| boolean isXmlValid = false; |
| |
| // A collection instance to hold validation error messages. |
| ArrayList validationMessages = new ArrayList(); |
| |
| // Validate the XML, collecting messages. |
| isXmlValid = xml.validate(new XmlOptions().setErrorListener(validationMessages)); |
| |
| if (!isXmlValid) |
| { |
| System.out.println("Invalid XML: "); |
| for (int i = 0; i < validationMessages.size(); i++) |
| { |
| XmlError error = (XmlError) validationMessages.get(i); |
| System.out.println(error.getMessage()); |
| System.out.println(error.getObjectLocation()); |
| } |
| } |
| return isXmlValid; |
| } |
| |
| /** |
| * <p>Creates a File from the XML path provided in main arguments, then |
| * parses the file's contents into a type generated from schema.</p> |
| * <p/> |
| * <p>Note that this work might have been done in main. Isolating it here |
| * makes the code separately available from outside this class.</p> |
| * |
| * @param xmlFilePath A path to XML based on the schema in inventory.xsd. |
| * @return An instance of a generated schema type that contains the parsed |
| * XML. |
| */ |
| public PurchaseOrderDocument parseXml(String xmlFilePath) |
| { |
| File poFile = new File(xmlFilePath); |
| PurchaseOrderDocument poDoc = null; |
| try |
| { |
| poDoc = PurchaseOrderDocument.Factory.parse(poFile); |
| } catch (XmlException e) |
| { |
| e.printStackTrace(); |
| } catch (IOException e) |
| { |
| e.printStackTrace(); |
| } |
| return poDoc; |
| } |
| } |