View Javadoc

1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.domain.geoloc.service.geoloc;
24  
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.io.OutputStreamWriter;
28  import java.io.UnsupportedEncodingException;
29  import java.io.Writer;
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  import javax.xml.bind.JAXBContext;
34  import javax.xml.bind.JAXBException;
35  import javax.xml.bind.Marshaller;
36  
37  import net.sf.json.JSON;
38  import net.sf.json.JSONSerializer;
39  import net.sf.json.JsonConfig;
40  import net.sf.json.util.PropertyFilter;
41  
42  import com.gisgraphy.domain.geoloc.service.ServiceException;
43  import com.gisgraphy.domain.geoloc.service.errors.UnsupportedFormatException;
44  import com.gisgraphy.domain.valueobject.Constants;
45  import com.gisgraphy.domain.valueobject.GeolocResultsDto;
46  import com.gisgraphy.domain.valueobject.GisFeatureDistance;
47  import com.gisgraphy.domain.valueobject.GisgraphyServiceType;
48  import com.gisgraphy.domain.valueobject.Pagination;
49  import com.gisgraphy.domain.valueobject.Output.OutputFormat;
50  import com.sun.syndication.feed.module.georss.GeoRSSModule;
51  import com.sun.syndication.feed.module.georss.gml.GMLModuleImpl;
52  import com.sun.syndication.feed.module.opensearch.OpenSearchModule;
53  import com.sun.syndication.feed.module.opensearch.impl.OpenSearchModuleImpl;
54  import com.sun.syndication.feed.synd.SyndContent;
55  import com.sun.syndication.feed.synd.SyndContentImpl;
56  import com.sun.syndication.feed.synd.SyndEntry;
57  import com.sun.syndication.feed.synd.SyndEntryImpl;
58  import com.sun.syndication.feed.synd.SyndFeed;
59  import com.sun.syndication.feed.synd.SyndFeedImpl;
60  import com.sun.syndication.io.SyndFeedOutput;
61  
62  /**
63   * serialize @link {@link GeolocResultsDto} into several formats
64   * 
65   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
66   */
67  public class GeolocResultsDtoSerializer implements
68  	IGeolocResultsDtoSerializer {
69      
70      private static JAXBContext contextForList;
71  
72      /**
73       * Json filter, to not serialize all the properties
74       */
75      protected JsonConfig jsonConfig = new JsonConfig();
76  
77      /**
78       * Default Constructor
79       */
80      public GeolocResultsDtoSerializer() {
81  	super();
82  	try {
83  	    contextForList = JAXBContext.newInstance(GeolocResultsDto.class);
84  	    jsonConfig.setIgnoreTransientFields(true);// does not seems to
85  	    // work
86  	    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
87  		public boolean apply(Object source, String name, Object value) {
88  		    if (name.contains("location")
89  			    || name.contains("gisFeature")) {
90  			return true;
91  		    }
92  		    return false;
93  		}
94  	    });
95  	} catch (JAXBException e) {
96  	    throw new GeolocSearchException(e.getMessage(), e.getCause());
97  	}
98      }
99  
100     /*
101      * (non-Javadoc)
102      * 
103      * @see
104      * com.gisgraphy.domain.geoloc.service.geoloc.IGisFeatureDistanceSerializer
105      * #serialize(java.io.OutputStream,
106      * com.gisgraphy.domain.valueobject.Output.OutputFormat,
107      * com.gisgraphy.domain.valueobject.GeolocResultsDto)
108      */
109     public void serialize(OutputStream outputStream, OutputFormat outputFormat,
110 	    GeolocResultsDto geolocResultsDto, boolean indent,int startPaginationIndex) {
111 	if (!outputFormat.isSupported(GisgraphyServiceType.GEOLOC)) {
112 	    throw new UnsupportedFormatException(outputFormat
113 		    + " is not applicable for Geoloc");
114 	} 
115 	   
116 	else if (outputFormat == OutputFormat.JSON) {
117 	    serializeToJSON(outputStream,
118 		    geolocResultsDto,indent);
119 	} else 	if (outputFormat==OutputFormat.ATOM){
120 	    serializeToFeed(outputStream,geolocResultsDto,OutputFormat.ATOM_VERSION, startPaginationIndex);
121 	}
122 	else if (outputFormat==OutputFormat.GEORSS) {
123 	    serializeToFeed(outputStream,geolocResultsDto,OutputFormat.RSS_VERSION, startPaginationIndex);
124 	}
125 	else {
126 	    //default
127 	    serializeToXML(outputStream,
128 		    geolocResultsDto,indent);
129 	}
130 	
131 	return;
132     }
133     
134     private void serializeToXML(OutputStream outputStream,
135 	    GeolocResultsDto geolocResultsDto,boolean indent) {
136 	 try {
137 		Marshaller m = contextForList.createMarshaller();
138 		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, indent);
139 		m.marshal(geolocResultsDto, outputStream);
140 	    } catch (Exception e) {
141 		throw new ServiceException(e);
142 	    }
143     }
144     
145     private void serializeToJSON(OutputStream outputStream,
146 	    GeolocResultsDto geolocResultsDto,boolean indent){
147     /*
148      * JSONArray jsonArray =
149      * JSONArray.fromObject(results,this.jsonConfig ); int indentFactor =
150      * query.isOutputIndented()?DEFAULT_INDENT_FACTOR:0;
151      * jsonArray.toString(indentFactor);
152      */
153     // for performance reason json is not indented
154     JSON json = JSONSerializer.toJSON(geolocResultsDto, jsonConfig);
155     final Writer writer;
156     try {
157 	writer = new OutputStreamWriter(outputStream, Constants.CHARSET);
158     } catch (Exception e) {
159 	throw new GeolocSearchException("unknow encoding "
160 		+ Constants.CHARSET, e);
161     }
162 
163     json.write(writer);
164     try {
165 	writer.flush();
166     } catch (IOException e) {
167 	throw new GeolocSearchException("error during flush", e);
168     }
169 }
170 
171     @SuppressWarnings("unchecked")
172     private void serializeToFeed(OutputStream outputStream,
173 	    GeolocResultsDto geolocResultsDto,String feedVersion, int startPaginationIndex) {
174 	SyndFeed synFeed = new SyndFeedImpl();
175 	Writer oWriter = null;
176 	try {
177 
178 	    synFeed.setFeedType(feedVersion);
179 	    
180 
181 	    synFeed.setTitle(Constants.FEED_TITLE);
182 	    synFeed.setLink(Constants.FEED_LINK);
183 	    synFeed.setDescription(Constants.FEED_DESCRIPTION);
184 	    List<SyndEntry> entries = new ArrayList<SyndEntry>();
185 
186 	    for (GisFeatureDistance gisFeatureDistance : geolocResultsDto
187 		    .getResult()) {
188 
189 		SyndEntry entry = new SyndEntryImpl();
190 		GeoRSSModule geoRSSModuleGML = new GMLModuleImpl();
191 		OpenSearchModule openSearchModule = new OpenSearchModuleImpl();
192 
193 		geoRSSModuleGML.setLatitude(gisFeatureDistance.getLat());
194 		geoRSSModuleGML.setLongitude(gisFeatureDistance.getLng());
195 
196 		openSearchModule
197 			.setItemsPerPage(Pagination.DEFAULT_MAX_RESULTS);
198 		openSearchModule
199 			.setTotalResults(geolocResultsDto.getNumFound());
200 		openSearchModule.setStartIndex(startPaginationIndex);
201 
202 		entry.getModules().add(openSearchModule);
203 		entry.getModules().add(geoRSSModuleGML);
204 		entry.setTitle(gisFeatureDistance.getName());
205 		entry.setAuthor(Constants.MAIL_ADDRESS);
206 		entry
207 			.setLink(Constants.GISFEATURE_BASE_URL+
208 				+ gisFeatureDistance.getFeatureId());
209 		SyndContent description = new SyndContentImpl();
210 		description.setType(OutputFormat.ATOM.getContentType());
211 		description.setValue(gisFeatureDistance.getName());
212 		entry.setDescription(description);
213 		entries.add(entry);
214 	    }
215 	    
216 	    synFeed.setEntries(entries);
217 
218 	    try {
219 		oWriter = new OutputStreamWriter(outputStream, Constants.CHARSET);
220 	    } catch (UnsupportedEncodingException e) {
221 		throw new RuntimeException("unknow encoding "+Constants.CHARSET);
222 	    }
223 
224 	    // Copy synfeed to output
225 	    SyndFeedOutput output = new SyndFeedOutput();
226 	    try {
227 		output.output(synFeed, oWriter);
228 		 // Flush
229 		    oWriter.flush();
230 	    } catch (Exception e) {
231 		throw new RuntimeException(e);
232 	    }
233 
234 	   
235 	} finally {
236 	    if (oWriter != null)
237 		try {
238 		    oWriter.close();
239 		} catch (IOException e) {
240 		    throw new RuntimeException(e);
241 		}
242 	    if (outputStream != null)
243 		try {
244 		    outputStream.close();
245 		} catch (IOException e) {
246 		    throw new RuntimeException(e);
247 		}
248 	}
249 
250     }
251 
252 }