/* 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.output;
import com.google.gdata.model.Element;
import com.google.gdata.model.ElementMetadata;
import com.google.gdata.wireformats.ContentValidationException;
import com.google.gdata.wireformats.WireFormat;
import com.google.gdata.wireformats.WireFormatGenerator;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
/**
* An {@link OutputGenerator} using a {@link WireFormat} to serialize to the
* output stream.
*
* @param <T> the expected object type handled by the generator
*
*
*/
public abstract class WireFormatOutputGenerator<T>
extends CharacterGenerator<T> {
/**
* Returns the wire format to use when generating this output.
*/
public abstract WireFormat getWireFormat();
/**
* Generates content to the writer based upon the provided request/response.
*/
@Override
public void generate(Writer w, OutputProperties outProps, T source)
throws IOException {
// Only types that extends Element are supported by the wire format code
if (source instanceof Element) {
Element elem = (Element) source;
try {
ElementMetadata<?, ?> outputMetadata = outProps.getRootMetadata();
if (outputMetadata == null) {
throw new IllegalStateException("No metadata for " +
elem.getElementKey());
}
elem = elem.resolve(outputMetadata);
// The outputMetadata in the properties could be for a base type that
// is broader than the element passed in. In this case, we want to
// re-bind to the more specific metadata and use that in the output
// properties passed to generate.
if (!elem.getElementKey().equals(outputMetadata.getKey())) {
outputMetadata =
outputMetadata.getSchema().bind(elem.getElementKey(),
outputMetadata.getContext());
if (outputMetadata == null) {
throw new IllegalStateException("Unable to rebind from " +
outProps.getRootMetadata().getKey() + " to " +
elem.getElementKey());
}
outProps =
new OutputPropertiesBuilder(outProps)
.setElementMetadata(outputMetadata)
.build();
}
WireFormat wireFormat = getWireFormat();
String encoding = getCharsetEncoding(outProps);
Charset cs = Charset.forName(encoding);
WireFormatGenerator gen = wireFormat.createGenerator(
outProps, w, cs, usePrettyPrint(outProps));
gen.generate(elem);
} catch (ContentValidationException e) {
throw new IOException("Invalid content: " + e.getMessage());
}
w.flush();
} else {
throw new IllegalArgumentException("Output object was not an Element: " +
source);
}
}
}