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.GisgraphyServiceType;
47  import com.gisgraphy.domain.valueobject.Pagination;
48  import com.gisgraphy.domain.valueobject.StreetDistance;
49  import com.gisgraphy.domain.valueobject.StreetSearchResultsDto;
50  import com.gisgraphy.domain.valueobject.Output.OutputFormat;
51  import com.sun.syndication.feed.module.georss.GeoRSSModule;
52  import com.sun.syndication.feed.module.georss.gml.GMLModuleImpl;
53  import com.sun.syndication.feed.module.opensearch.OpenSearchModule;
54  import com.sun.syndication.feed.module.opensearch.impl.OpenSearchModuleImpl;
55  import com.sun.syndication.feed.synd.SyndContent;
56  import com.sun.syndication.feed.synd.SyndContentImpl;
57  import com.sun.syndication.feed.synd.SyndEntry;
58  import com.sun.syndication.feed.synd.SyndEntryImpl;
59  import com.sun.syndication.feed.synd.SyndFeed;
60  import com.sun.syndication.feed.synd.SyndFeedImpl;
61  import com.sun.syndication.io.SyndFeedOutput;
62  
63  /**
64   * serialize @link {@link GeolocResultsDto} into several formats
65   * 
66   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
67   */
68  public class StreetSearchResultsDtoSerializer implements
69  	IStreetSearchResultsDtoSerializer {
70      
71      private static JAXBContext contextForList;
72  
73      /**
74       * Json filter, to not serialize all the properties
75       */
76      protected JsonConfig jsonConfig = new JsonConfig();
77  
78      /**
79       * Default Constructor
80       */
81      public StreetSearchResultsDtoSerializer() {
82  	super();
83  	try {
84  	    contextForList = JAXBContext.newInstance(StreetSearchResultsDto.class);
85  	    jsonConfig.setIgnoreTransientFields(true);// does not seems to
86  	    // work
87  	    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
88  		public boolean apply(Object source, String name, Object value) {
89  		    if (name.contains("location")
90  			    || name.contains("gisFeature")) {
91  			return true;
92  		    }
93  		    return false;
94  		}
95  	    });
96  	} catch (JAXBException e) {
97  	    throw new GeolocSearchException(e.getMessage(), e.getCause());
98  	}
99      }
100 
101    
102 
103     public void serialize(OutputStream outputStream, OutputFormat outputFormat,
104 	    StreetSearchResultsDto streetSearchResultsDto, boolean indent,int startPaginationIndex) {
105 	if (!outputFormat.isSupported(GisgraphyServiceType.STREET)) {
106 	    throw new UnsupportedFormatException(outputFormat
107 		    + " is not applicable for street search");
108 	} 
109 	   
110 	else if (outputFormat == OutputFormat.JSON) {
111 	    serializeToJSON(outputStream,
112 		    streetSearchResultsDto,indent);
113 	} else 	if (outputFormat==OutputFormat.ATOM){
114 	    serializeToFeed(outputStream,streetSearchResultsDto,OutputFormat.ATOM_VERSION, startPaginationIndex);
115 	}
116 	else if (outputFormat==OutputFormat.GEORSS) {
117 	    serializeToFeed(outputStream,streetSearchResultsDto,OutputFormat.RSS_VERSION, startPaginationIndex);
118 	}
119 	else {
120 	    //default
121 	    serializeToXML(outputStream,
122 		    streetSearchResultsDto,indent);
123 	}
124 	
125 	return;
126     }
127     
128     private void serializeToXML(OutputStream outputStream,
129 	    StreetSearchResultsDto streetSearchResultsDto,boolean indent) {
130 	 try {
131 		Marshaller m = contextForList.createMarshaller();
132 		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, indent);
133 		m.marshal(streetSearchResultsDto, outputStream);
134 	    } catch (Exception e) {
135 		throw new ServiceException(e);
136 	    }
137     }
138     
139     private void serializeToJSON(OutputStream outputStream,
140 	    StreetSearchResultsDto streetSearchResultsDto,boolean indent){
141     /*
142      * JSONArray jsonArray =
143      * JSONArray.fromObject(results,this.jsonConfig ); int indentFactor =
144      * query.isOutputIndented()?DEFAULT_INDENT_FACTOR:0;
145      * jsonArray.toString(indentFactor);
146      */
147     // for performance reason json is not indented
148     JSON json = JSONSerializer.toJSON(streetSearchResultsDto, jsonConfig);
149     final Writer writer;
150     try {
151 	writer = new OutputStreamWriter(outputStream, Constants.CHARSET);
152     } catch (Exception e) {
153 	throw new GeolocSearchException("unknow encoding "
154 		+ Constants.CHARSET, e);
155     }
156 
157     json.write(writer);
158     try {
159 	writer.flush();
160     } catch (IOException e) {
161 	throw new GeolocSearchException("error during flush", e);
162     }
163 }
164 
165     @SuppressWarnings("unchecked")
166     private void serializeToFeed(OutputStream outputStream,
167 	    StreetSearchResultsDto streetSearchResultsDto,String feedVersion, int startPaginationIndex) {
168 	SyndFeed synFeed = new SyndFeedImpl();
169 	Writer oWriter = null;
170 	try {
171 
172 	    synFeed.setFeedType(feedVersion);
173 	    
174 
175 	    synFeed.setTitle(Constants.FEED_TITLE);
176 	    synFeed.setLink(Constants.FEED_LINK);
177 	    synFeed.setDescription(Constants.FEED_DESCRIPTION);
178 	    List<SyndEntry> entries = new ArrayList<SyndEntry>();
179 
180 	    for (StreetDistance gisFeatureDistance : streetSearchResultsDto
181 		    .getResult()) {
182 
183 		SyndEntry entry = new SyndEntryImpl();
184 		GeoRSSModule geoRSSModuleGML = new GMLModuleImpl();
185 		OpenSearchModule openSearchModule = new OpenSearchModuleImpl();
186 
187 		geoRSSModuleGML.setLatitude(gisFeatureDistance.getLat());
188 		geoRSSModuleGML.setLongitude(gisFeatureDistance.getLng());
189 
190 		openSearchModule
191 			.setItemsPerPage(Pagination.DEFAULT_MAX_RESULTS);
192 		openSearchModule
193 			.setTotalResults(streetSearchResultsDto.getNumFound());
194 		openSearchModule.setStartIndex(startPaginationIndex);
195 
196 		entry.getModules().add(openSearchModule);
197 		entry.getModules().add(geoRSSModuleGML);
198 		entry.setTitle(gisFeatureDistance.getName());
199 		entry.setAuthor(Constants.MAIL_ADDRESS);
200 		entry
201 			.setLink(Constants.STREET_BASE_URL+
202 				+ gisFeatureDistance.getGid());
203 		SyndContent description = new SyndContentImpl();
204 		description.setType(OutputFormat.ATOM.getContentType());
205 		description.setValue(gisFeatureDistance.getName());
206 		entry.setDescription(description);
207 		entries.add(entry);
208 	    }
209 	    
210 	    synFeed.setEntries(entries);
211 
212 	    try {
213 		oWriter = new OutputStreamWriter(outputStream, Constants.CHARSET);
214 	    } catch (UnsupportedEncodingException e) {
215 		throw new RuntimeException("unknow encoding "+Constants.CHARSET);
216 	    }
217 
218 	    // Copy synfeed to output
219 	    SyndFeedOutput output = new SyndFeedOutput();
220 	    try {
221 		output.output(synFeed, oWriter);
222 		 // Flush
223 		    oWriter.flush();
224 	    } catch (Exception e) {
225 		throw new RuntimeException(e);
226 	    }
227 
228 	   
229 	} finally {
230 	    if (oWriter != null)
231 		try {
232 		    oWriter.close();
233 		} catch (IOException e) {
234 		    throw new RuntimeException(e);
235 		}
236 	    if (outputStream != null)
237 		try {
238 		    outputStream.close();
239 		} catch (IOException e) {
240 		    throw new RuntimeException(e);
241 		}
242 	}
243 
244     }
245 
246 }