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  /**
24   *
25   */
26  package com.gisgraphy.domain.valueobject;
27  
28  import org.apache.commons.lang.NotImplementedException;
29  
30  import com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor;
31  import com.gisgraphy.domain.geoloc.service.errors.UnsupportedFormatException;
32  import com.gisgraphy.domain.geoloc.service.fulltextsearch.FullTextFields;
33  import com.gisgraphy.domain.geoloc.service.geoloc.GeolocErrorVisitor;
34  
35  /**
36   * Represent an output specification.
37   * 
38   * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
39   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
40   */
41  public class Output {
42  
43      /**
44       * All the possible fulltext search output format, all the OUTPUFORMAT enum
45       * should be in uppercase
46       */
47      public enum OutputFormat {
48  	/**
49  	 * 
50  	 */
51  	XML {
52  	    /*
53  	     * (non-Javadoc)
54  	     * 
55  	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
56  	     */
57  	    @Override
58  	    public String getParameterValue() {
59  		return "standard";
60  	    }
61  
62  	    /*
63  	     * (non-Javadoc)
64  	     * 
65  	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
66  	     */
67  	    @Override
68  	    public String getContentType() {
69  		return "application/xml";
70  	    }
71  
72  	    /*
73  	     * (non-Javadoc)
74  	     * 
75  	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
76  	     */
77  	    @Override
78  	    public String accept(IoutputFormatVisitor visitor) {
79  		return visitor.visitXML(this);
80  	    }
81  	    
82  	    /* (non-Javadoc)
83  	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
84  	     */
85  	    @Override
86  	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
87  	       return true;
88  	    }
89  
90  	},
91  	JSON {
92  	    /*
93  	     * (non-Javadoc)
94  	     * 
95  	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
96  	     */
97  	    @Override
98  	    public String getParameterValue() {
99  		return "json";
100 	    }
101 
102 	    /*
103 	     * (non-Javadoc)
104 	     * 
105 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
106 	     */
107 	    @Override
108 	    public String getContentType() {
109 		return "application/json";
110 	    }
111 
112 	    /*
113 	     * (non-Javadoc)
114 	     * 
115 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
116 	     */
117 	    @Override
118 	    public String accept(IoutputFormatVisitor visitor) {
119 		return visitor.visitJSON(this);
120 	    }
121 	    
122 	    /* (non-Javadoc)
123 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
124 	     */
125 	    @Override
126 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
127 	       return true;
128 	    }
129 	},
130 	PYTHON {
131 	    /*
132 	     * (non-Javadoc)
133 	     * 
134 	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
135 	     */
136 	    @Override
137 	    public String getParameterValue() {
138 		return "python";
139 	    }
140 
141 	    /*
142 	     * (non-Javadoc)
143 	     * 
144 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
145 	     */
146 	    @Override
147 	    public String getContentType() {
148 		return "text/plain";
149 	    }
150 
151 	    /*
152 	     * (non-Javadoc)
153 	     * 
154 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
155 	     */
156 	    @Override
157 	    public String accept(IoutputFormatVisitor visitor) {
158 		return visitor.visitPYTHON(this);
159 	    }
160 	    
161 	    /* (non-Javadoc)
162 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
163 	     */
164 	    @Override
165 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
166 	       return gisgraphyServiceType == GisgraphyServiceType.FULLTEXT;
167 	    }
168 	},
169 	PHP {
170 	    /*
171 	     * (non-Javadoc)
172 	     * 
173 	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
174 	     */
175 	    @Override
176 	    public String getParameterValue() {
177 		return "php";
178 	    }
179 
180 	    /*
181 	     * (non-Javadoc)
182 	     * 
183 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
184 	     */
185 	    @Override
186 	    public String getContentType() {
187 		return "text/plain";
188 	    }
189 
190 	    /*
191 	     * (non-Javadoc)
192 	     * 
193 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
194 	     */
195 	    @Override
196 	    public String accept(IoutputFormatVisitor visitor) {
197 		return visitor.visitPHP(this);
198 	    }
199 	    
200 	    /* (non-Javadoc)
201 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
202 	     */
203 	    @Override
204 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
205 	       return gisgraphyServiceType == GisgraphyServiceType.FULLTEXT;
206 	    }
207 	},
208 	ATOM {
209 	    /*
210 	     * (non-Javadoc)
211 	     * 
212 	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
213 	     */
214 	    @Override
215 	    public String getParameterValue() {
216 		return "xslt";
217 	    }
218 
219 	    /*
220 	     * (non-Javadoc)
221 	     * 
222 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
223 	     */
224 	    @Override
225 	    public String getContentType() {
226 		return "application/xml";
227 	    }
228 
229 	    /*
230 	     * (non-Javadoc)
231 	     * 
232 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
233 	     */
234 	    @Override
235 	    public String accept(IoutputFormatVisitor visitor) {
236 		return visitor.visitATOM(this);
237 	    }
238 	    
239 	    /* (non-Javadoc)
240 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
241 	     */
242 	    @Override
243 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
244 	       return true;
245 	    }
246 	},
247 	GEORSS {
248 	    /*
249 	     * (non-Javadoc)
250 	     * 
251 	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
252 	     */
253 	    @Override
254 	    public String getParameterValue() {
255 		return "xslt";
256 	    }
257 
258 	    /*
259 	     * (non-Javadoc)
260 	     * 
261 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
262 	     */
263 	    @Override
264 	    public String getContentType() {
265 		return "application/xml";
266 	    }
267 
268 	    /*
269 	     * (non-Javadoc)
270 	     * 
271 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
272 	     */
273 	    @Override
274 	    public String accept(IoutputFormatVisitor visitor) {
275 		return visitor.visitGEORSS(this);
276 	    }
277 	    
278 	    /* (non-Javadoc)
279 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
280 	     */
281 	    @Override
282 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
283 	       return true;
284 	    }
285 	},
286 	RUBY {
287 	    /*
288 	     * (non-Javadoc)
289 	     * 
290 	     * @see com.gisgraphy.domain.geoloc.service.Output.OutputFormat#getParameterValue()
291 	     */
292 	    @Override
293 	    public String getParameterValue() {
294 		return "ruby";
295 	    }
296 
297 	    /*
298 	     * (non-Javadoc)
299 	     * 
300 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#getContentType()
301 	     */
302 	    @Override
303 	    public String getContentType() {
304 		return "text/plain";
305 	    }
306 
307 	    /*
308 	     * (non-Javadoc)
309 	     * 
310 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#accept(com.gisgraphy.domain.geoloc.service.errors.IoutputFormatVisitor)
311 	     */
312 	    @Override
313 	    public String accept(IoutputFormatVisitor visitor) {
314 		return visitor.visitRUBY(this);
315 	    }
316 	    
317 	    /* (non-Javadoc)
318 	     * @see com.gisgraphy.domain.valueobject.Output.OutputFormat#isSupported(com.gisgraphy.domain.valueobject.Output.OutputFormat, com.gisgraphy.domain.valueobject.GisgraphyServiceType)
319 	     */
320 	    @Override
321 	    public boolean isSupported(GisgraphyServiceType gisgraphyServiceType) {
322 	       return gisgraphyServiceType == GisgraphyServiceType.FULLTEXT;
323 	    }
324 	};
325 
326 	/**
327 	 * @return The default format
328 	 */
329 	public static OutputFormat getDefault() {
330 	    return OutputFormat.XML;
331 	}
332 
333 	/**
334 	 * @return The value of the parameter (e.g : the query type for fulltext
335 	 *         query)
336 	 */
337 	public abstract String getParameterValue();
338 
339 	/**
340 	 * @return The value of the HTTP contenttype associated to the Output
341 	 *         format
342 	 */
343 	public abstract String getContentType();
344 
345 	/**
346 	 * @param format
347 	 *                the format as String
348 	 * @return the outputFormat from the String or the default OutputFormat
349 	 *         if the format can not be determine
350 	 * @see #getDefault()
351 	 */
352 	public static OutputFormat getFromString(String format) {
353 	    OutputFormat outputFormat = OutputFormat.getDefault();
354 	    try {
355 		outputFormat = OutputFormat.valueOf(format.toUpperCase());
356 	    } catch (RuntimeException e) {
357 	    }
358 	    return outputFormat;
359 
360 	}
361 
362 	/**
363 	 * @param format
364 	 *                the format to check
365 	 * @param serviceType
366 	 *                the service type we'd like to know if the format is
367 	 *                applicable
368 	 * @return the format if the format is applicable for the service or the
369 	 *         default one.
370 	 * @throws UnsupportedFormatException
371 	 *                 if the service is not implemented by the algorithm
372 	 */
373 	public static OutputFormat getDefaultForServiceIfNotSupported(OutputFormat format,
374 		GisgraphyServiceType serviceType) {
375 	    switch (serviceType) {
376 	    case FULLTEXT:
377 		// fulltext accept all formats
378 		return format.isSupported(serviceType)==true?format:getDefault();
379 	    case GEOLOC:
380 		return format.isSupported(serviceType)==true?format:getDefault();
381 	    case STREET:
382 		return format.isSupported(serviceType)==true?format:getDefault();
383 	    default:
384 		throw new UnsupportedFormatException("The service type "
385 			+ serviceType + "is not implemented");
386 	    }
387 	}
388 
389 	/**
390 	 * @param serviceType the type of service we'd like to know if the format is supported
391 	 * @return true if the format is supported by the specified {@link GisgraphyServiceType}
392 	 */
393 	public abstract boolean isSupported(GisgraphyServiceType serviceType);
394 	
395 	/**
396 	 * @param serviceType
397 	 *                the service type we'd like to know all the formats
398 	 * @return the formats for the specified service
399 	 * @throws NotImplementedException
400 	 *                 if the service is not implemented by the algorithm
401 	 */
402 	public static OutputFormat[] listByService(
403 		GisgraphyServiceType serviceType) {
404 	    switch (serviceType) {
405 	    case FULLTEXT:
406 		// fulltext accept all formats
407 		return OutputFormat.values();
408 	    case GEOLOC:
409 		OutputFormat[] resultGeoloc = { OutputFormat.XML, OutputFormat.JSON, OutputFormat.ATOM, OutputFormat.GEORSS };
410 		return resultGeoloc;
411 		
412 	    case STREET:
413 		OutputFormat[] resultStreet = { OutputFormat.XML, OutputFormat.JSON, OutputFormat.ATOM, OutputFormat.GEORSS };
414 		return resultStreet;
415 	    default:
416 		throw new NotImplementedException("The service type "
417 			+ serviceType + "is not implemented");
418 	    }
419 
420 	}
421 	
422 	public static final String RSS_VERSION = "rss_2.0";
423 	
424 	public static final String ATOM_VERSION = "atom_0.3";
425 
426 	/**
427 	 * Method to implement the visitor pattern
428 	 * 
429 	 * @param visitor
430 	 *                accept a visitor
431 	 * @return a string return by the visitor
432 	 * @see IoutputFormatVisitor
433 	 * @see GeolocErrorVisitor
434 	 */
435 	public abstract String accept(IoutputFormatVisitor visitor);
436 
437     }
438 
439     /**
440      * All the possible fulltext search output style verbosity Short (basic
441      * informations) : feature_id, name, fully_qualified_name, zipcode (if
442      * city), placetype, country_code, country_name<br/> Medium (More
443      * informations) : Short + lat, lon, feature_class, feature_code,
444      * population, fips<br/> Long (AlternateNames +adm informations) : Medium +
445      * alternateNames, adm1_name, adm2_name, adm3_name, Adm4_name, adm1_code,
446      * Adm2_code, Adm3_code, Adm4_code<br/> Full (alternatenames for adm and
447      * country): Long + country_alternate_name_, adm1_alternate_name_,
448      * adm2_alternate_name_<br/>
449      */
450     public enum OutputStyle {
451 	SHORT {
452 
453 	    /*
454 	     * (non-Javadoc)
455 	     * 
456 	     * @see com.gisgraphy.domain.geoloc.service.fulltextsearch.Output.OutputStyle#getFieldList()
457 	     */
458 	    @Override
459 	    public String getFieldList(String languageCode) {
460 		return new StringBuffer("score,").append(
461 			FullTextFields.FEATUREID.getValue()).append(",")
462 			.append(FullTextFields.NAME.getValue()).append(",")
463 			.append(FullTextFields.FULLY_QUALIFIED_NAME.getValue())
464 			.append(",").append(FullTextFields.ZIPCODE.getValue())
465 			.append(",")
466 			.append(FullTextFields.PLACETYPE.getValue())
467 			.append(",").append(
468 				FullTextFields.COUNTRYCODE.getValue()).append(
469 				",").append(
470 				FullTextFields.COUNTRYNAME.getValue())
471 			.toString();
472 	    }
473 	},
474 	MEDIUM {
475 
476 	    /*
477 	     * (non-Javadoc)
478 	     * 
479 	     * @see com.gisgraphy.domain.geoloc.service.fulltextsearch.Output.OutputStyle#getFieldList()
480 	     */
481 	    @Override
482 	    public String getFieldList(String languageCode) {
483 		return new StringBuffer(SHORT.getFieldList(languageCode))
484 			.append(",").append(FullTextFields.LAT.getValue())
485 			.append(",").append(FullTextFields.LONG.getValue())
486 			.append(",").append(
487 				FullTextFields.FEATURECLASS.getValue()).append(
488 				",").append(
489 				FullTextFields.FEATURECODE.getValue()).append(
490 				",").append(
491 				FullTextFields.POPULATION.getValue()).append(
492 				",")
493 			.append(FullTextFields.NAMEASCII.getValue())
494 			.append(",").append(FullTextFields.TIMEZONE.getValue())
495 			.append(",").append(FullTextFields.ELEVATION.getValue())
496 			
497 			//country fields only
498 			.append(",").append(FullTextFields.CONTINENT.getValue())
499 			.append(",").append(FullTextFields.CURRENCY_CODE.getValue())
500 			.append(",").append(FullTextFields.CURRENCY_NAME.getValue())
501 			.append(",").append(FullTextFields.FIPS_CODE.getValue())
502 			.append(",").append(FullTextFields.ISOALPHA2_COUNTRY_CODE.getValue())
503 			.append(",").append(FullTextFields.ISOALPHA3_COUNTRY_CODE.getValue())
504 			.append(",").append(FullTextFields.POSTAL_CODE_MASK.getValue())
505 			.append(",").append(FullTextFields.POSTAL_CODE_REGEX.getValue())
506 			.append(",").append(FullTextFields.PHONE_PREFIX.getValue())
507 			.append(",").append(FullTextFields.SPOKEN_LANGUAGES.getValue())
508 			.append(",").append(FullTextFields.TLD.getValue())
509 			.append(",").append(FullTextFields.CAPITAL_NAME.getValue())
510 			.append(",").append(FullTextFields.AREA.getValue())
511 			
512 			//adm only
513 			.append(",").append(FullTextFields.LEVEL.getValue())
514 			
515 			.append(",").append(FullTextFields.GTOPO30.getValue())
516 			.append(",").append(
517 				FullTextFields.COUNTRY_FLAG_URL.getValue())
518 			.append(",").append(
519 				FullTextFields.GOOGLE_MAP_URL.getValue())
520 			.append(",").append(
521 				FullTextFields.YAHOO_MAP_URL.getValue())
522 			.toString();
523 	    }
524 	},
525 	LONG {
526 
527 	    /*
528 	     * (non-Javadoc)
529 	     * 
530 	     * @see com.gisgraphy.domain.geoloc.service.fulltextsearch.Output.OutputStyle#getFieldList()
531 	     */
532 	    @Override
533 	    public String getFieldList(String languageCode) {
534 		StringBuffer sb = new StringBuffer(MEDIUM
535 			.getFieldList(languageCode)).append(",").append(
536 			FullTextFields.ADM1NAME.getValue()).append(",").append(
537 			FullTextFields.ADM2NAME.getValue()).append(",").append(
538 			FullTextFields.ADM3NAME.getValue()).append(",").append(
539 			FullTextFields.ADM4NAME.getValue()).append(",").append(
540 			FullTextFields.ADM1CODE.getValue()).append(",").append(
541 			FullTextFields.ADM2CODE.getValue()).append(",").append(
542 			FullTextFields.ADM3CODE.getValue()).append(",").append(
543 			FullTextFields.ADM4CODE.getValue());
544 		return sb.toString();
545 
546 	    }
547 	},
548 	FULL {
549 
550 	    /*
551 	     * (non-Javadoc)
552 	     * 
553 	     * @see com.gisgraphy.domain.geoloc.service.fulltextsearch.Output.OutputStyle#getFieldList()
554 	     */
555 	    @Override
556 	    public String getFieldList(String languageCode) {
557 		if (languageCode != null) {
558 		    StringBuffer sb = new StringBuffer(LONG
559 			    .getFieldList(languageCode)).append(",").append(
560 			    FullTextFields.COUNTRYNAME.getValue()).append(
561 			    FullTextFields.ALTERNATE_NAME_SUFFIX.getValue())
562 			    .append(",").append(
563 				    FullTextFields.ADM1NAME.getValue()).append(
564 				    FullTextFields.ALTERNATE_NAME_SUFFIX
565 					    .getValue()).append(",").append(
566 				    FullTextFields.ADM2NAME.getValue()).append(
567 				    FullTextFields.ALTERNATE_NAME_SUFFIX
568 					    .getValue()).append(",").append(
569 				    FullTextFields.NAME.getValue()).append(
570 				    FullTextFields.ALTERNATE_NAME_DYNA_SUFFIX
571 					    .getValue()).append(languageCode)
572 			    .append(",").append(FullTextFields.NAME.getValue())
573 			    .append(
574 				    FullTextFields.ALTERNATE_NAME_SUFFIX
575 					    .getValue()).append(",").append(
576 				    FullTextFields.COUNTRYNAME.getValue())
577 			    .append(
578 				    FullTextFields.ALTERNATE_NAME_DYNA_SUFFIX
579 					    .getValue()).append(languageCode)
580 			    .append(",").append(
581 				    FullTextFields.ADM1NAME.getValue()).append(
582 				    FullTextFields.ALTERNATE_NAME_DYNA_SUFFIX
583 					    .getValue()).append(languageCode)
584 			    .append(",").append(
585 				    FullTextFields.ADM2NAME.getValue()).append(
586 				    FullTextFields.ALTERNATE_NAME_DYNA_SUFFIX
587 					    .getValue()).append(languageCode);
588 
589 		    return sb.toString();
590 		} else {
591 		    return "*,score";
592 		}
593 	    }
594 	};
595 
596 	/**
597 	 * @return the list of field tha the format must return
598 	 */
599 	public abstract String getFieldList(String languageCode);
600 
601 	/**
602 	 * @return the default outputStyle
603 	 */
604 	public static OutputStyle getDefault() {
605 	    return OutputStyle.MEDIUM;
606 	}
607 
608 	/**
609 	 * @param style
610 	 *                the style as String
611 	 * @return the outputStyle from the String or the default OutputStyle if
612 	 *         the style can not be determine
613 	 * @see #getDefault()
614 	 */
615 	public static OutputStyle getFromString(String style) {
616 	    OutputStyle outputStyle = OutputStyle.getDefault();
617 	    try {
618 		outputStyle = OutputStyle.valueOf(style.toUpperCase());
619 	    } catch (RuntimeException e) {
620 	    }
621 	    return outputStyle;
622 
623 	}
624 
625     }
626 
627     // output fields
628     /**
629      * The default output format
630      */
631   //  public static final OutputFormat DEFAULT_OUTPUT_FORMAT = OutputFormat.XML;
632 
633     /**
634      * The Default Output style
635      */
636     //public static final OutputStyle DEFAULT_OUTPUT_STYLE = OutputStyle.getDefault();
637 
638     /**
639      * The Default {@link #languageCode}
640      */
641     public static final String DEFAULT_LANGUAGE_CODE = null;
642 
643    
644     /**
645      * The output format value default to {@link OutputFormat#XML}
646      */
647     private OutputFormat format = OutputFormat.getDefault();
648 
649     /**
650      * the iso639 Alpha2 LanguageCode, default to {@link #DEFAULT_LANGUAGE_CODE}
651      */
652     private String languageCode = Output.DEFAULT_LANGUAGE_CODE;
653 
654     /**
655      * The output style verbosity, default to {@link #DEFAULT_OUTPUT_STYLE}
656      */
657     private OutputStyle style =  OutputStyle.MEDIUM;
658 
659     private boolean indent = false;
660 
661     /**
662      * Default contructor with format
663      */
664     private Output(OutputFormat format) {
665 	if (format == null) {
666 	    this.format = OutputFormat.getDefault();
667 	} else {
668 	    this.format = format;
669 	}
670     }
671 
672     /**
673      * @param format
674      *                The format the output shoud have
675      * @return an output specification with the specified format
676      */
677     public static Output withFormat(OutputFormat format) {
678 	return new Output(format);
679     }
680 
681     /**
682      * @return an output specification with default output format
683      * @see OutputFormat#getDefault()
684      */
685     public static Output withDefaultFormat() {
686 	return new Output(OutputFormat.getDefault());
687     }
688 
689     /**
690      * @return the list of fields that will be returned in the output according
691      *         to the {@link #getLanguageCode()} and {@link OutputStyle} (the
692      *         fields return by the full text search engine)
693      */
694     public String getFields() {
695 	return this.style.getFieldList(languageCode);
696     }
697 
698     /**
699      * @return the format, default is {@link OutputFormat#getDefault()}
700      * @see #withFormat(com.gisgraphy.domain.valueobject.Output.OutputFormat)
701      */
702     public OutputFormat getFormat() {
703 	return format;
704     }
705 
706     /**
707      * @return the iso639 Alpha2 LanguageCode, default is
708      *         {@link Output#DEFAULT_LANGUAGE_CODE}
709      * @see #withLanguageCode(String)
710      */
711     public String getLanguageCode() {
712 	return languageCode;
713     }
714 
715     /**
716      * @return the style, default is {@link OutputStyle#getDefault()}
717      * @see #withStyle(com.gisgraphy.domain.valueobject.Output.OutputStyle)
718      */
719     public OutputStyle getStyle() {
720 	return style;
721     }
722 
723     /**
724      * @return wether the output must be indent, default to false
725      * @see #withIndentation()
726      */
727     public boolean isIndented() {
728 	return indent;
729     }
730 
731     /**
732      * This method force the output to be indented
733      * 
734      * @return the current Object instance in order to chain methods
735      * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
736      */
737     public Output withIndentation() {
738 	this.indent = true;
739 	return this;
740     }
741 
742     /**
743      * @param languageCode
744      *                The iso639Alpha2 LanguageCode parameter that the output
745      *                format should be, the fulltext results will be in the
746      *                specified language The language code can be null or a non
747      *                existing language code (no check is done).if the specified
748      *                languageCode is null or an empty string, it will be set to
749      *                null
750      * @return the current Object instance in order to chain methods
751      * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
752      */
753     public Output withLanguageCode(String languageCode) {
754 	if (languageCode == null || "".equals(languageCode.trim())) {
755 	    this.languageCode = DEFAULT_LANGUAGE_CODE;
756 	} else {
757 	    this.languageCode = languageCode.toUpperCase();
758 	}
759 	return this;
760     }
761 
762     /**
763      * @param style
764      *                The verbosity style parameter that the output format
765      *                should have, the output will include more or less data
766      *                according to the specified style
767      * @return the current Object instance in order to chain methods
768      * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
769      */
770     public Output withStyle(OutputStyle style) {
771 	if (style == null) {
772 	    this.style = OutputStyle.MEDIUM;
773 	} else {
774 	    this.style = style;
775 	}
776 	return this;
777     }
778 
779     /*
780      * (non-Javadoc)
781      * 
782      * @see java.lang.Object#toString()
783      */
784     @Override
785     public String toString() {
786 	return "output in " + format + ", in " + style
787 		+ " style with language " + languageCode + " and ident="
788 		+ isIndented();
789     }
790     
791     /**
792      * Output with default values
793      */
794     public static final Output DEFAULT_OUTPUT = Output.withFormat(OutputFormat.XML)
795 	    .withStyle(OutputStyle.MEDIUM).withLanguageCode(
796 		    Output.DEFAULT_LANGUAGE_CODE);
797 
798     /* (non-Javadoc)
799      * @see java.lang.Object#hashCode()
800      */
801     @Override
802     public int hashCode() {
803 	final int prime = 31;
804 	int result = 1;
805 	result = prime * result + ((format == null) ? 0 : format.hashCode());
806 	result = prime * result + (indent ? 1231 : 1237);
807 	result = prime * result
808 		+ ((languageCode == null) ? 0 : languageCode.hashCode());
809 	result = prime * result + ((style == null) ? 0 : style.hashCode());
810 	return result;
811     }
812 
813     /* (non-Javadoc)
814      * @see java.lang.Object#equals(java.lang.Object)
815      */
816     @Override
817     public boolean equals(Object obj) {
818 	if (this == obj)
819 	    return true;
820 	if (obj == null)
821 	    return false;
822 	if (getClass() != obj.getClass())
823 	    return false;
824 	final Output other = (Output) obj;
825 	if (format == null) {
826 	    if (other.format != null)
827 		return false;
828 	} else if (!format.equals(other.format))
829 	    return false;
830 	if (indent != other.indent)
831 	    return false;
832 	if (languageCode == null) {
833 	    if (other.languageCode != null)
834 		return false;
835 	} else if (!languageCode.equals(other.languageCode))
836 	    return false;
837 	if (style == null) {
838 	    if (other.style != null)
839 		return false;
840 	} else if (!style.equals(other.style))
841 	    return false;
842 	return true;
843     }
844 
845 }