/* Copyright (c) 2008 Google Inc.
*
* 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 com.google.gdata.wireformats.input;
import com.google.gdata.data.ParseSource;
import com.google.gdata.util.ParseException;
import com.google.gdata.util.ServiceException;
import com.google.gdata.wireformats.AltFormat;
import com.google.gdata.util.io.base.UnicodeReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
/**
* The CharacterParser class is abstract base class to support the
* implementation of an {@link InputParser} for character-based content types.
* <p>
* It encapsulates the code for mapping from an {@link InputStream} to an
* {@link Reader} based upon the input content type and then delegates to the
* abstract {@link #parse(Reader, InputProperties, Class)} method to handle
* the actual parsing of the character data.
*
*
*/
public abstract class CharacterParser<T> extends AbstractParser<T> {
/**
* Constructs a new CharacterParser that parses content in a particular
* alt format and returns instances of the specified type.
*
* @param altFormat representation handled by this parser
* @param resultClass base type of results produced by parser.
*/
protected CharacterParser(AltFormat altFormat, Class<T> resultClass) {
super(altFormat, resultClass);
}
/**
* Returns the expected character set encoding for content based upon the
* input properties content type.
*
* @param inProps input properties
* @return expected character set encoding
*/
protected String getCharset(InputProperties inProps) {
return inProps.getContentType().getCharset();
}
/**
* The parse method will use the character encoding found in the output
* properties instance to construct an appropriate {@link Reader} and then
* delegate to the {@link #parse(Reader, InputProperties, Class)} method
* to perform the parsing.
*/
public <R extends T> R parse(ParseSource parseSource, InputProperties inProps,
Class<R> targetClass) throws IOException, ServiceException {
Reader reader;
reader = parseSource.getReader();
if (reader == null) {
InputStream inputStream = parseSource.getInputStream();
if (inputStream != null) {
try {
String charset = getCharset(inProps);
if (charset == null) {
// case where charset has not been specified in the Content-Type.
charset = "UTF-8";
}
if (charset.toLowerCase().startsWith("utf-")) {
reader = new UnicodeReader(inputStream, charset);
} else {
reader = new InputStreamReader(inputStream, charset);
}
} catch (UnsupportedEncodingException e) {
throw new ParseException("Unsupported encoding: " +
e.getLocalizedMessage(), e);
}
} else {
// Means an XmlEventSource was passed in, should be handled at a higher
// level by XmlInputParser
throw new IllegalStateException("XML event source not supported");
}
}
return parse(reader, inProps, targetClass);
}
/**
* Parses character content with the specified properties to produce a result
* of an expected type. Concrete subclasses will provide an implementation
* of this method that constructs a result type instance of the result class
* and then parses into it from the provided {@link Reader}.
*
* @param <R> expected result type
* @param inputReader reader to parse data from
* @param inProps input properties
* @param resultClass class to instantiate and parse result into.
* @return result object from parse
* @throws IOException if an error occurred reading data while parsing
* @throws ServiceException if an error occurred within the content
*/
abstract public <R extends T> R parse(Reader inputReader,
InputProperties inProps, Class<R> resultClass)
throws IOException, ServiceException;
}