Oracle® Application Development Framework Developer's Guide
10g Release 3 (10.1.3) B25386-01 |
|
![]() Previous |
![]() Next |
This section shows the contents of the following files:
Example 20-37 shows the contents of the sampleDC.xsd
file.
Example 20-37 sampleDC.xsd
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xmlns.oracle.com/adfm/adapter/test" xmlns="http://xmlns.oracle.com/adfm/adapter/test" elementFormDefault="qualified"> <xsd:element name="Definition"> <xsd:complexType> <xsd:attribute name="SourceLocation" type="xsd:string"/> </xsd:complexType> </xsd:element> </xsd:schema>
Example 20-38 shows the contents of the CSVHandler
class.
Example 20-38 CSVHandler
package oracle.adfinternal.model.adapter.sample; import java.io.InputStream; import java.util.Iterator; import java.util.List; import java.util.Map; import oracle.binding.meta.DefinitionContext; import oracle.binding.meta.StructureDefinition; import oracle.adf.model.utils.SimpleStringBuffer; import oracle.adf.model.adapter.AdapterException; import oracle.adf.model.adapter.dataformat.AttributeDef; import oracle.adf.model.adapter.dataformat.StructureDef; import oracle.adfinternal.model.adapter.sample.CSVParser; import oracle.adf.model.adapter.utils.Utility; /** * Format handler for character separated values. * <p> * This class generates structures according to the JSR 227 specification from * a CSV data stream by parsing the data. The data types are guessed from the * value of the first data line. It can extract values from a CSV data stream * as well. * <p> * Data controls that deals with CSV data can use this class to generate data * and structure. * * @version 1.0 * @since 10.1.3 */ public class CSVHandler { // stream containing the data. private InputStream mDataStream; // if the first row contains the names private boolean mIsFirstRowNames = false; // Encoding styles private String mEncStyle; // Character value separator private String mDelimiter; // Character used to quote a multi-word string private String mQuoteChar; // Column names private List mColNames = null; ////////////////////////////// Constructors ////////////////////////////////// /** * Creats a CSV format handler object. * * @param is input stream that contains the CSV data. * @param isFirstRowNames flag to indicate if the first row of the CSV data * can be treated as column names. * @param encodingStyle encoding style of the data. * @param delim character value separators. * @param quoteChar value that can be treated as quote. */ public CSVHandler( InputStream is, boolean isFirstRowNames, String encodingStyle, String delim, String quoteChar) { mDataStream = is; mIsFirstRowNames = isFirstRowNames; mEncStyle = encodingStyle; mDelimiter = delim; mQuoteChar = quoteChar; } ///////////////////// Impl of FormatHandler ////////////////////////////////// /** * Returns the structure definition extracted for the data format. * <p> * * @param name name of the root structure. * @param ctx definition context information. * @return the structure information extracted. */ public StructureDefinition getStructure(String name, DefinitionContext ctx) { StructureDef attrParent = null; try { CSVParser parser; if (mEncStyle == null) { parser = new CSVParser(mDataStream); } else { parser = new CSVParser(mDataStream, mEncStyle); } parser.setSeparators(mDelimiter.toCharArray()); if (mQuoteChar != null && mQuoteChar.length() != 0) { parser.setQuoteChar(mQuoteChar.charAt(0)); } // Get the column names Iterator colNames = getColNames(parser).iterator(); // Create the structure definition attrParent = new StructureDef(name); // Parse the data to get the attributes if (mIsFirstRowNames) { parser.nextLine(); } String[] vals = parser.getLineValues(); if (vals != null) { int i = 0; while (colNames.hasNext()) { String type = "java.lang.String"; if (i < vals.length) { type = checkType(vals[i]); ++i; } AttributeDef attr = new AttributeDef((String) colNames.next(), attrParent, type); attrParent.addAttribute(attr); } } else { while (colNames.hasNext()) { AttributeDef attr = new AttributeDef((String) colNames.next(), attrParent, "java.lang.String"); attrParent.addAttribute(attr); } } } catch (Exception e) { throw new AdapterException(e); } return attrParent; } /** * Returns the resulting data extracted from the input. * @param params parameters passed containig the context information. * @return <code>Iterator</code> of <code>Map</code> objects for the result. * If no data found it can return null. The <code>Map</code> * contains the value of attributes as defined in the data structure. * For complex data, <code>Map</code>s can contain other iterator of * <code>Map</code>s as well. */ public Iterator getResult(Map params) { try { final CSVParser parser; if (mEncStyle == null) { parser = new CSVParser(mDataStream); } else { parser = new CSVParser(mDataStream, mEncStyle); } parser.setSeparators(mDelimiter.toCharArray()); if (mQuoteChar != null && mQuoteChar.length() != 0) { parser.setQuoteChar(mQuoteChar.charAt(0)); } final List cols = getColNames(parser); final boolean bEndOfData = (mIsFirstRowNames) ? !parser.nextLine() : false; //return the data iterator return new Iterator() { CSVParser _parser = parser; Iterator _colNames = cols.iterator(); boolean _eof = bEndOfData; public void remove() { } public boolean hasNext() { return !_eof; } public Object next() { try { if (_eof) { return null; } java.util.HashMap map = new java.util.HashMap(5); // Create the current row as Map String[] data = _parser.getLineValues(); int i = 0; while (_colNames.hasNext()) { String val = null; if (i < data.length) { val = data[i]; } map.put(_colNames.next(), val); i++; } // get the next data line. _eof = !_parser.nextLine(); return map; } catch (Exception e) { throw new AdapterException(e); } } }; } catch (AdapterException ae) { throw ae; } catch (Exception e) { throw new AdapterException(e); } } //============================================================================ // Class Helper Methods //============================================================================ /** * Attempts to obtain the Java type from the string value. * @param data String value whose datatype has to be guessed. * @return Java type name. */ private String checkType(String data) { try { // We first try to convert the value into a long number. // If successful, we will use long; if it throws NumberFormatException, // we will attempt to convert it to float. If this too fails, we return // string. if (data != null) { try { // Try to conver the value into an integer number. long numTest = Long.parseLong(data); return "java.lang.Long"; //NOTRANS } catch (NumberFormatException nfe) { // Try to convert the value into float number. float numTest = Float.parseFloat(data); return "java.lang.Float"; //NOTRANS } } else { return "java.lang.String"; //NOTRANS } } catch (NumberFormatException nfe) { // If conversion failed, we assume this is a string. return "java.lang.String"; } } /** * Gets the column names. */ /** * Gets the column names. */ private List getColNames(CSVParser parser) { try { if (mColNames == null) { // Get the first row. If the first row is NOT the column names, we need // to generate column names for them. if (!parser.nextLine()) { // No data found. // ToDo: resource new Exception("No data"); } mColNames = new java.util.ArrayList(10); String[] cols = parser.getLineValues(); if (mIsFirstRowNames) { makeValidColumnNames(cols); for (int i = 0; i < cols.length; i++) { mColNames.add(cols[i]); } } else { for (int i = 0; i < cols.length; i++) { String colName = new SimpleStringBuffer(20).append("Column").append(i).toString(); mColNames.add(colName); } } } return mColNames; } catch (Exception e) { throw new AdapterException(e); } } /** * Make valid column names for all columns in CSV data source. * * This method applies the following rules to translate the given string * to a valid column name which can be accepted by EL: * * 1. If the first character of the string is digit, * prefix the string with '_'. * 2. Translate any characters other than letter, digit, or '_' to '_'. * * */ private String[] makeValidColumnNames(String[] cols) { for (int i = 0; i <cols.length; i++) { // Trim out leading or ending white spaces if (cols[i] != null && cols[i].length() > 0) { cols[i] = cols[i].trim(); } if (cols[i] == null || cols[i].length() == 0) { // Default as "column1", "column2", ... if column name null cols[i] = new SimpleStringBuffer("column").append(i+1).toString(); } else { // Check special characters try { cols[i] = Utility.normalizeString(cols[i]); } catch (Exception e) { // On error, simply default to "columnX". cols[i] = new SimpleStringBuffer("column").append(i+1).toString(); } } } return cols; } }
Example 20-39 shows the contents of the CSVParser
class.
Example 20-39 CSVParser
package oracle.adfinternal.model.adapter.sample; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.ArrayList; import oracle.adf.model.utils.SimpleStringBuffer; public final class CSVParser { /////////////////////////////// Constants //////////////////////////////////// /** UTF8 encoding, used for hadling data in different languages. */ public static final String UTF8_ENCODING = "UTF8"; /** Quote character */ private static char CHAR_QUOTE = '"'; /** Comma (seperator) character */ private static char CHAR_COMMA = ','; /////////////////////////////// Class Variables ////////////////////////////// /** * CSV stream reader */ private LineNumberReader mReader; /** Buffer to store one line of values. */ private ArrayList mValueArrayList = new ArrayList(); /** Buffer to store one string value. */ private SimpleStringBuffer mValueBuffer = new SimpleStringBuffer(256); /** Current processed line. */ private String mLine = null; /** Current character position in the current line. */ private int mLinePosition = -1; /** Length of current line. */ private int mLineLength = 0; /** If last character is comma. */ private boolean mLastCharIsComma = false; /** Value separator character set. The separator can be one of these values.*/ private char[] mSepCharSet = {CHAR_COMMA}; /** Quote character. */ private char mQuoteChar = CHAR_QUOTE; ////////////////////////////// Constructors ////////////////////////////////// /** * Constructor * * @param pInputStream CSV input stream * @throws Exception any error occurred */ public CSVParser(InputStream pInputStream) throws Exception { // If no encoding is passed in, use "UTF-8" encoding this(pInputStream, UTF8_ENCODING); } /** * Constructor * * @param pInputStream CSV input stream * @param pEnc character encoding * @throws Exception any error occurred */ public CSVParser(InputStream pInputStream, String pEnc) throws Exception { if (pInputStream == null) { throw new Exception("Null Input Stream."); //TODO: Resource } mReader = new LineNumberReader(new InputStreamReader(pInputStream, pEnc)); } ///////////////////////////// Public Methods ///////////////////////////////// /** * Sets the separator characters as a list of possible separators for the * data. CSV data may have more than one separators. By default this parser * considers comma (,) as the data separator. * @param seps Array of separator charactors. */ public void setSeparators(char[] seps) { if ((seps != null) && (seps.length > 0)) { mSepCharSet = seps; } } /** * Sets the quote character. * @param ch Quote character. */ public void setQuoteChar(char ch) { mQuoteChar = ch; } /** * Moves to the next line of the data. * @return returns false if the end of data reached. * @throws Exception any error occurred */ public boolean nextLine() throws Exception { setLine(mReader.readLine()); if (mLine == null) { // End of file mValueArrayList.clear(); return false; } parseLine(); return true; } /** * Gets values of next line. * @return next line elements from input stream. If end of data reached, * it returns null. * @throws Exception any error occurred */ public String[] getLineValues() throws Exception { if (mValueArrayList.size() > 0) { String[] ret = new String[mValueArrayList.size()]; return (String[]) mValueArrayList.toArray(ret); } return null; } //////////////////////////// Class Helpers /////////////////////////////////// /** * Checks if the character is a valid separator. */ private boolean isSeparator(char ch) { for (int i = 0; i < mSepCharSet.length; i++) { if (ch == mSepCharSet[i]) { return true; } } return false; } /** * Tests if end of line has reached. * @return true if end of line. */ public boolean isEndOfLine() { // If last char is comma, must return at least one more value return (mLinePosition >= mLineLength) && (!mLastCharIsComma); } /** * Sets current line to be processed * * @param line the line to be processed */ private void setLine(String line) { mLine = line; if (line != null) { mLineLength = line.length(); mLinePosition = 0; } } /** * If next character is quote character * * @return true if next character is quote */ private boolean isNextCharQuote() { if ((mLinePosition + 1) >= mLineLength) { // no more char in the line return false; } else { char ch = mLine.charAt(mLinePosition + 1); if (ch == mQuoteChar) { return true; } else { return false; } } } /** * Parse one line. * * @return values of the line * @throws Exception any error occurred */ private void parseLine() throws Exception { mValueArrayList.clear(); String[] values = null; String value = null; while (!isEndOfLine()) { value = getNextValue(); mValueArrayList.add(value); } } /** * Gets next value from current line. * @return next data value. */ private String getNextValue() throws Exception { mLastCharIsComma = false; // Clean up value buffer first if (mValueBuffer.length() > 0) { mValueBuffer.setLength(0); } boolean insideQuote = false; boolean firstChar = true; boolean endValue = false; // Scan char by char while ((mLinePosition < mLineLength) && !endValue) { boolean copyChar = true; char ch = mLine.charAt(mLinePosition); // If first char if (firstChar) { // Only check quote at first char if (ch == mQuoteChar) { insideQuote = true; copyChar = false; } // Also need to check comma at first char else if (isSeparator(ch)) { copyChar = false; endValue = true; mLastCharIsComma = true; } firstChar = false; } // Not first char but inside quote else if (insideQuote) { // Check end quote if (ch == mQuoteChar) { copyChar = false; // Two sucesstive quote chars inside quote means quote char itself if (isNextCharQuote()) { mLinePosition++; } // Otherwise it is ending quote else { insideQuote= false; } } } // Not first char and outside quote else { // Check comma if (isSeparator(ch)) { copyChar = false; endValue = true; mLastCharIsComma = true; } } if (copyChar) { mValueBuffer.append(ch); } mLinePosition++; } if (mValueBuffer.length() > 0) { return mValueBuffer.toString(); } else { return null; } } }