/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.stanbol.entityhub.web.writer;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Iterator;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.stanbol.entityhub.servicesapi.model.Representation;
import org.apache.stanbol.entityhub.web.ModelWriter;
import org.apache.stanbol.entityhub.web.ModelWriterRegistry;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(immediate=true)
@Service(Object.class)
@Property(name="javax.ws.rs", boolValue=true)
@Provider
public class RepresentationWriter implements MessageBodyWriter<Representation> {
private final Logger log = LoggerFactory.getLogger(RepresentationWriter.class);
@Reference
protected ModelWriterRegistry writerRegistry;
@Override
public long getSize(Representation t,
Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType) {
return -1;
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
if(Representation.class.isAssignableFrom(type)){
if(mediaType.isWildcardType() && mediaType.isWildcardSubtype()){
mediaType = ModelWriter.DEFAULT_MEDIA_TYPE;
}
return writerRegistry.isWriteable(getMatchType(mediaType), null);
} else {
return false;
}
}
@Override
public void writeTo(Representation rep,
Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String,Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
//check for wildcard
if(mediaType.isWildcardType() && mediaType.isWildcardSubtype()){
mediaType = ModelWriter.DEFAULT_MEDIA_TYPE;
}
String charset = mediaType.getParameters().get("charset");
if(charset == null){
charset = ModelWriter.DEFAULT_CHARSET;
mediaType = mediaType.withCharset(charset);
httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, mediaType.toString());
}
Iterator<ServiceReference> refs = writerRegistry.getModelWriters(
getMatchType(mediaType), rep.getClass()).iterator();
ModelWriter writer = null;
MediaType selectedMediaType = null;
while((writer == null || selectedMediaType == null) && refs.hasNext()){
writer = writerRegistry.getService(refs.next());
if(writer != null){
if(mediaType.isWildcardType() || mediaType.isWildcardSubtype()){
selectedMediaType = writer.getBestMediaType(mediaType);
} else {
selectedMediaType = mediaType;
}
}
}
selectedMediaType = selectedMediaType.withCharset(charset);
httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, mediaType.toString());
if(writer == null || selectedMediaType == null){
throw new WebApplicationException("Unable to serialize "+rep.getClass().getName()+" to "+mediaType);
}
log.debug("serialize {} with ModelWriter {}",rep.getClass().getName(), writer.getClass().getName());
writer.write(rep, entityStream, selectedMediaType);
}
/**
* Strips all parameters from the parsed mediaType
* @param mediaType
*/
protected MediaType getMatchType(MediaType mediaType) {
final MediaType matchType;
if(!mediaType.getParameters().isEmpty()){
matchType = new MediaType(mediaType.getType(), mediaType.getSubtype());
} else {
matchType = mediaType;
}
return matchType;
}
}