Source Code Cross Referenced for JSONResponseWriter.java in  » Search-Engine » apache-solr-1.2.0 » org » apache » solr » request » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Search Engine » apache solr 1.2.0 » org.apache.solr.request 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */package org.apache.solr.request;
017:
018:        import org.apache.lucene.document.Document;
019:        import org.apache.lucene.document.Fieldable;
020:        import org.apache.solr.schema.SchemaField;
021:        import org.apache.solr.schema.TextField;
022:        import org.apache.solr.search.DocIterator;
023:        import org.apache.solr.search.DocList;
024:        import org.apache.solr.search.SolrIndexSearcher;
025:        import org.apache.solr.util.NamedList;
026:        import org.apache.solr.util.SimpleOrderedMap;
027:
028:        import java.io.IOException;
029:        import java.io.Writer;
030:        import java.util.*;
031:
032:        /**
033:         * @author yonik
034:         * @version $Id$
035:         */
036:
037:        public class JSONResponseWriter implements  QueryResponseWriter {
038:            static String CONTENT_TYPE_JSON_UTF8 = "text/x-json; charset=UTF-8";
039:
040:            public void init(NamedList n) {
041:            }
042:
043:            public void write(Writer writer, SolrQueryRequest req,
044:                    SolrQueryResponse rsp) throws IOException {
045:                JSONWriter w = new JSONWriter(writer, req, rsp);
046:                w.writeResponse();
047:            }
048:
049:            public String getContentType(SolrQueryRequest request,
050:                    SolrQueryResponse response) {
051:                // using the text/plain allows this to be viewed in the browser easily
052:                return CONTENT_TYPE_TEXT_UTF8;
053:            }
054:        }
055:
056:        class JSONWriter extends TextResponseWriter {
057:
058:            // cache the calendar instance in case we are writing many dates...
059:            private Calendar cal;
060:
061:            private String namedListStyle;
062:            private String wrapperFunction;
063:
064:            private static final String JSON_NL_STYLE = "json.nl";
065:            private static final String JSON_NL_MAP = "map";
066:            private static final String JSON_NL_FLAT = "flat";
067:            private static final String JSON_NL_ARROFARR = "arrarr";
068:            private static final String JSON_NL_ARROFMAP = "arrmap";
069:            private static final String JSON_WRAPPER_FUNCTION = "json.wrf";
070:
071:            public JSONWriter(Writer writer, SolrQueryRequest req,
072:                    SolrQueryResponse rsp) {
073:                super (writer, req, rsp);
074:                namedListStyle = req.getParams().get(JSON_NL_STYLE,
075:                        JSON_NL_FLAT).intern();
076:                wrapperFunction = req.getParams().get(JSON_WRAPPER_FUNCTION);
077:            }
078:
079:            public void writeResponse() throws IOException {
080:                if (wrapperFunction != null) {
081:                    writer.write(wrapperFunction + "(");
082:                }
083:                writeNamedList(null, rsp.getValues());
084:                if (wrapperFunction != null) {
085:                    writer.write(")");
086:                }
087:            }
088:
089:            protected void writeKey(String fname, boolean needsEscaping)
090:                    throws IOException {
091:                writeStr(null, fname, needsEscaping);
092:                writer.write(':');
093:            }
094:
095:            /** Represents a NamedList directly as a JSON Object (essentially a Map)
096:             * Map null to "" and name mangle any repeated keys to avoid repeats in the
097:             * output.
098:             */
099:            protected void writeNamedListAsMapMangled(String name, NamedList val)
100:                    throws IOException {
101:                int sz = val.size();
102:                writer.write('{');
103:                incLevel();
104:
105:                // In JSON objects (maps) we can't have null keys or duplicates...
106:                // map null to "" and append a qualifier to duplicates.
107:                //
108:                // a=123,a=456 will be mapped to {a=1,a__1=456}
109:                // Disad: this is ambiguous since a real key could be called a__1
110:                //
111:                // Another possible mapping could aggregate multiple keys to an array:
112:                // a=123,a=456 maps to a=[123,456]
113:                // Disad: this is ambiguous with a real single value that happens to be an array
114:                //
115:                // Both of these mappings have ambiguities.
116:                HashMap<String, Integer> repeats = new HashMap<String, Integer>(
117:                        4);
118:
119:                boolean first = true;
120:                for (int i = 0; i < sz; i++) {
121:                    String key = val.getName(i);
122:                    if (key == null)
123:                        key = "";
124:
125:                    if (first) {
126:                        first = false;
127:                        repeats.put(key, 0);
128:                    } else {
129:                        writer.write(',');
130:
131:                        Integer repeatCount = repeats.get(key);
132:                        if (repeatCount == null) {
133:                            repeats.put(key, 0);
134:                        } else {
135:                            String newKey = key;
136:                            int newCount = repeatCount;
137:                            do { // avoid generated key clashing with a real key
138:                                newKey = key + ' ' + (++newCount);
139:                                repeatCount = repeats.get(newKey);
140:                            } while (repeatCount != null);
141:
142:                            repeats.put(key, newCount);
143:                            key = newKey;
144:                        }
145:                    }
146:
147:                    indent();
148:                    writeKey(key, true);
149:                    writeVal(key, val.getVal(i));
150:                }
151:
152:                decLevel();
153:                writer.write('}');
154:            }
155:
156:            /** Represents a NamedList directly as a JSON Object (essentially a Map)
157:             * repeating any keys if they are repeated in the NamedList.  null is mapped
158:             * to "".
159:             */
160:            protected void writeNamedListAsMapWithDups(String name,
161:                    NamedList val) throws IOException {
162:                int sz = val.size();
163:                writer.write('{');
164:                incLevel();
165:
166:                for (int i = 0; i < sz; i++) {
167:                    if (i != 0) {
168:                        writer.write(',');
169:                    }
170:
171:                    String key = val.getName(i);
172:                    if (key == null)
173:                        key = "";
174:                    indent();
175:                    writeKey(key, true);
176:                    writeVal(key, val.getVal(i));
177:                }
178:
179:                decLevel();
180:                writer.write('}');
181:            }
182:
183:            // Represents a NamedList directly as an array of JSON objects...
184:            // NamedList("a"=1,"b"=2,null=3) => [{"a":1},{"b":2},3]
185:            protected void writeNamedListAsArrMap(String name, NamedList val)
186:                    throws IOException {
187:                int sz = val.size();
188:                indent();
189:                writer.write('[');
190:                incLevel();
191:
192:                boolean first = true;
193:                for (int i = 0; i < sz; i++) {
194:                    String key = val.getName(i);
195:
196:                    if (first) {
197:                        first = false;
198:                    } else {
199:                        writer.write(',');
200:                    }
201:
202:                    indent();
203:
204:                    if (key == null) {
205:                        writeVal(null, val.getVal(i));
206:                    } else {
207:                        writer.write('{');
208:                        writeKey(key, true);
209:                        writeVal(key, val.getVal(i));
210:                        writer.write('}');
211:                    }
212:
213:                }
214:
215:                decLevel();
216:                writer.write(']');
217:            }
218:
219:            // Represents a NamedList directly as an array of JSON objects...
220:            // NamedList("a"=1,"b"=2,null=3) => [["a",1],["b",2],[null,3]]
221:            protected void writeNamedListAsArrArr(String name, NamedList val)
222:                    throws IOException {
223:                int sz = val.size();
224:                indent();
225:                writer.write('[');
226:                incLevel();
227:
228:                boolean first = true;
229:                for (int i = 0; i < sz; i++) {
230:                    String key = val.getName(i);
231:
232:                    if (first) {
233:                        first = false;
234:                    } else {
235:                        writer.write(',');
236:                    }
237:
238:                    indent();
239:
240:                    /*** if key is null, just write value???
241:                    if (key==null) {
242:                      writeVal(null,val.getVal(i));
243:                    } else {
244:                     ***/
245:
246:                    writer.write('[');
247:                    incLevel();
248:                    writeStr(null, key, true);
249:                    writer.write(',');
250:                    writeVal(key, val.getVal(i));
251:                    decLevel();
252:                    writer.write(']');
253:
254:                }
255:
256:                decLevel();
257:                writer.write(']');
258:            }
259:
260:            // Represents a NamedList directly as an array with keys/values
261:            // interleaved.
262:            // NamedList("a"=1,"b"=2,null=3) => ["a",1,"b",2,null,3]
263:            protected void writeNamedListAsFlat(String name, NamedList val)
264:                    throws IOException {
265:                int sz = val.size();
266:                writer.write('[');
267:                incLevel();
268:
269:                for (int i = 0; i < sz; i++) {
270:                    if (i != 0) {
271:                        writer.write(',');
272:                    }
273:                    String key = val.getName(i);
274:                    indent();
275:                    if (key == null) {
276:                        writeNull(null);
277:                    } else {
278:                        writeStr(null, key, true);
279:                    }
280:                    writer.write(',');
281:                    writeVal(key, val.getVal(i));
282:                }
283:
284:                decLevel();
285:                writer.write(']');
286:            }
287:
288:            public void writeNamedList(String name, NamedList val)
289:                    throws IOException {
290:                if (val instanceof  SimpleOrderedMap) {
291:                    writeNamedListAsMapWithDups(name, val);
292:                } else if (namedListStyle == JSON_NL_FLAT) {
293:                    writeNamedListAsFlat(name, val);
294:                } else if (namedListStyle == JSON_NL_MAP) {
295:                    writeNamedListAsMapWithDups(name, val);
296:                } else if (namedListStyle == JSON_NL_ARROFARR) {
297:                    writeNamedListAsArrArr(name, val);
298:                } else if (namedListStyle == JSON_NL_ARROFMAP) {
299:                    writeNamedListAsArrMap(name, val);
300:                }
301:            }
302:
303:            private static class MultiValueField {
304:                final SchemaField sfield;
305:                final ArrayList<Fieldable> fields;
306:
307:                MultiValueField(SchemaField sfield, Fieldable firstVal) {
308:                    this .sfield = sfield;
309:                    this .fields = new ArrayList<Fieldable>(4);
310:                    this .fields.add(firstVal);
311:                }
312:            }
313:
314:            public void writeDoc(String name, Collection<Fieldable> fields,
315:                    Set<String> returnFields, Map pseudoFields)
316:                    throws IOException {
317:                writer.write('{');
318:                incLevel();
319:
320:                HashMap<String, MultiValueField> multi = new HashMap<String, MultiValueField>();
321:
322:                boolean first = true;
323:
324:                for (Fieldable ff : fields) {
325:                    String fname = ff.name();
326:                    if (returnFields != null && !returnFields.contains(fname)) {
327:                        continue;
328:                    }
329:
330:                    // if the field is multivalued, it may have other values further on... so
331:                    // build up a list for each multi-valued field.
332:                    SchemaField sf = schema.getField(fname);
333:                    if (sf.multiValued()) {
334:                        MultiValueField mf = multi.get(fname);
335:                        if (mf == null) {
336:                            mf = new MultiValueField(sf, ff);
337:                            multi.put(fname, mf);
338:                        } else {
339:                            mf.fields.add(ff);
340:                        }
341:                    } else {
342:                        // not multi-valued, so write it immediately.
343:                        if (first) {
344:                            first = false;
345:                        } else {
346:                            writer.write(',');
347:                        }
348:                        indent();
349:                        writeKey(fname, true);
350:                        sf.write(this , fname, ff);
351:                    }
352:                }
353:
354:                for (MultiValueField mvf : multi.values()) {
355:                    if (first) {
356:                        first = false;
357:                    } else {
358:                        writer.write(',');
359:                    }
360:
361:                    indent();
362:                    writeKey(mvf.sfield.getName(), true);
363:
364:                    boolean indentArrElems = false;
365:                    if (doIndent) {
366:                        // heuristic... TextField is probably the only field type likely to be long enough
367:                        // to warrant indenting individual values.
368:                        indentArrElems = (mvf.sfield.getType() instanceof  TextField);
369:                    }
370:
371:                    writer.write('[');
372:                    boolean firstArrElem = true;
373:                    incLevel();
374:
375:                    for (Fieldable ff : mvf.fields) {
376:                        if (firstArrElem) {
377:                            firstArrElem = false;
378:                        } else {
379:                            writer.write(',');
380:                        }
381:                        if (indentArrElems)
382:                            indent();
383:                        mvf.sfield.write(this , null, ff);
384:                    }
385:                    writer.write(']');
386:                    decLevel();
387:                }
388:
389:                if (pseudoFields != null && pseudoFields.size() > 0) {
390:                    writeMap(null, pseudoFields, true, first);
391:                }
392:
393:                decLevel();
394:                writer.write('}');
395:            }
396:
397:            // reusable map to store the "score" pseudo-field.
398:            // if a Doc can ever contain another doc, this optimization would have to go.
399:            private final HashMap scoreMap = new HashMap(1);
400:
401:            public void writeDoc(String name, Document doc,
402:                    Set<String> returnFields, float score, boolean includeScore)
403:                    throws IOException {
404:                Map other = null;
405:                if (includeScore) {
406:                    other = scoreMap;
407:                    scoreMap.put("score", score);
408:                }
409:                writeDoc(name, (List<Fieldable>) (doc.getFields()),
410:                        returnFields, other);
411:            }
412:
413:            public void writeDocList(String name, DocList ids,
414:                    Set<String> fields, Map otherFields) throws IOException {
415:                boolean includeScore = false;
416:                if (fields != null) {
417:                    includeScore = fields.contains("score");
418:                    if (fields.size() == 0
419:                            || (fields.size() == 1 && includeScore)
420:                            || fields.contains("*")) {
421:                        fields = null; // null means return all stored fields
422:                    }
423:                }
424:
425:                int sz = ids.size();
426:
427:                writer.write('{');
428:                incLevel();
429:                writeKey("numFound", false);
430:                writeInt(null, ids.matches());
431:                writer.write(',');
432:                writeKey("start", false);
433:                writeInt(null, ids.offset());
434:
435:                if (includeScore) {
436:                    writer.write(',');
437:                    writeKey("maxScore", false);
438:                    writeFloat(null, ids.maxScore());
439:                }
440:                writer.write(',');
441:                // indent();
442:                writeKey("docs", false);
443:                writer.write('[');
444:
445:                incLevel();
446:                boolean first = true;
447:
448:                SolrIndexSearcher searcher = req.getSearcher();
449:                DocIterator iterator = ids.iterator();
450:                for (int i = 0; i < sz; i++) {
451:                    int id = iterator.nextDoc();
452:                    Document doc = searcher.doc(id, fields);
453:
454:                    if (first) {
455:                        first = false;
456:                    } else {
457:                        writer.write(',');
458:                    }
459:                    indent();
460:                    writeDoc(null, doc, fields, (includeScore ? iterator
461:                            .score() : 0.0f), includeScore);
462:                }
463:                decLevel();
464:                writer.write(']');
465:
466:                if (otherFields != null) {
467:                    writeMap(null, otherFields, true, false);
468:                }
469:
470:                decLevel();
471:                indent();
472:                writer.write('}');
473:            }
474:
475:            public void writeStr(String name, String val, boolean needsEscaping)
476:                    throws IOException {
477:                writer.write('"');
478:                // it might be more efficient to use a stringbuilder or write substrings
479:                // if writing chars to the stream is slow.
480:                if (needsEscaping) {
481:
482:                    /* http://www.ietf.org/internet-drafts/draft-crockford-jsonorg-json-04.txt
483:                     All Unicode characters may be placed within
484:                     the quotation marks except for the characters which must be
485:                     escaped: quotation mark, reverse solidus, and the control
486:                     characters (U+0000 through U+001F).
487:                     */
488:
489:                    for (int i = 0; i < val.length(); i++) {
490:                        char ch = val.charAt(i);
491:                        switch (ch) {
492:                        case '"':
493:                        case '\\':
494:                            writer.write('\\');
495:                            writer.write(ch);
496:                            break;
497:                        case '\r':
498:                            writer.write("\\r");
499:                            break;
500:                        case '\n':
501:                            writer.write("\\n");
502:                            break;
503:                        case '\t':
504:                            writer.write("\\t");
505:                            break;
506:                        case '\b':
507:                            writer.write("\\b");
508:                            break;
509:                        case '\f':
510:                            writer.write("\\f");
511:                            break;
512:                        // case '/':
513:                        default: {
514:                            if (ch <= 0x1F) {
515:                                unicodeEscape(writer, ch);
516:                            } else {
517:                                writer.write(ch);
518:                            }
519:                        }
520:                        }
521:                    }
522:                } else {
523:                    writer.write(val);
524:                }
525:                writer.write('"');
526:            }
527:
528:            public void writeMap(String name, Map val, boolean excludeOuter,
529:                    boolean isFirstVal) throws IOException {
530:                if (!excludeOuter) {
531:                    writer.write('{');
532:                    incLevel();
533:                    isFirstVal = true;
534:                }
535:
536:                boolean doIndent = excludeOuter || val.size() > 1;
537:
538:                for (Map.Entry entry : (Set<Map.Entry>) val.entrySet()) {
539:                    Object e = entry.getKey();
540:                    String k = e == null ? "" : e.toString();
541:                    Object v = entry.getValue();
542:
543:                    if (isFirstVal) {
544:                        isFirstVal = false;
545:                    } else {
546:                        writer.write(',');
547:                    }
548:
549:                    if (doIndent)
550:                        indent();
551:                    writeKey(k, true);
552:                    writeVal(k, v);
553:                }
554:
555:                if (!excludeOuter) {
556:                    decLevel();
557:                    writer.write('}');
558:                }
559:            }
560:
561:            public void writeArray(String name, Object[] val)
562:                    throws IOException {
563:                writeArray(name, Arrays.asList(val).iterator());
564:            }
565:
566:            public void writeArray(String name, Iterator val)
567:                    throws IOException {
568:                writer.write('[');
569:                incLevel();
570:                boolean first = true;
571:                while (val.hasNext()) {
572:                    if (!first)
573:                        indent();
574:                    writeVal(null, val.next());
575:                    if (val.hasNext()) {
576:                        writer.write(',');
577:                    }
578:                    first = false;
579:                }
580:                decLevel();
581:                writer.write(']');
582:            }
583:
584:            //
585:            // Primitive types
586:            //
587:            public void writeNull(String name) throws IOException {
588:                writer.write("null");
589:            }
590:
591:            public void writeInt(String name, String val) throws IOException {
592:                writer.write(val);
593:            }
594:
595:            public void writeLong(String name, String val) throws IOException {
596:                writer.write(val);
597:            }
598:
599:            public void writeBool(String name, String val) throws IOException {
600:                writer.write(val);
601:            }
602:
603:            public void writeFloat(String name, String val) throws IOException {
604:                writer.write(val);
605:            }
606:
607:            public void writeDouble(String name, String val) throws IOException {
608:                writer.write(val);
609:            }
610:
611:            // TODO: refactor this out to a DateUtils class or something...
612:            public void writeDate(String name, Date val) throws IOException {
613:                // using a stringBuilder for numbers can be nice since
614:                // a temporary string isn't used (it's added directly to the
615:                // builder's buffer.
616:
617:                StringBuilder sb = new StringBuilder();
618:                if (cal == null)
619:                    cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
620:                cal.setTime(val);
621:
622:                int i = cal.get(Calendar.YEAR);
623:                sb.append(i);
624:                sb.append('-');
625:                i = cal.get(Calendar.MONTH) + 1; // 0 based, so add 1
626:                if (i < 10)
627:                    sb.append('0');
628:                sb.append(i);
629:                sb.append('-');
630:                i = cal.get(Calendar.DAY_OF_MONTH);
631:                if (i < 10)
632:                    sb.append('0');
633:                sb.append(i);
634:                sb.append('T');
635:                i = cal.get(Calendar.HOUR_OF_DAY); // 24 hour time format
636:                if (i < 10)
637:                    sb.append('0');
638:                sb.append(i);
639:                sb.append(':');
640:                i = cal.get(Calendar.MINUTE);
641:                if (i < 10)
642:                    sb.append('0');
643:                sb.append(i);
644:                sb.append(':');
645:                i = cal.get(Calendar.SECOND);
646:                if (i < 10)
647:                    sb.append('0');
648:                sb.append(i);
649:                i = cal.get(Calendar.MILLISECOND);
650:                if (i != 0) {
651:                    sb.append('.');
652:                    if (i < 100)
653:                        sb.append('0');
654:                    if (i < 10)
655:                        sb.append('0');
656:                    sb.append(i);
657:
658:                    // handle canonical format specifying fractional
659:                    // seconds shall not end in '0'.  Given the slowness of
660:                    // integer div/mod, simply checking the last character
661:                    // is probably the fastest way to check.
662:                    int lastIdx = sb.length() - 1;
663:                    if (sb.charAt(lastIdx) == '0') {
664:                        lastIdx--;
665:                        if (sb.charAt(lastIdx) == '0') {
666:                            lastIdx--;
667:                        }
668:                        sb.setLength(lastIdx + 1);
669:                    }
670:
671:                }
672:                sb.append('Z');
673:                writeDate(name, sb.toString());
674:            }
675:
676:            public void writeDate(String name, String val) throws IOException {
677:                writeStr(name, val, false);
678:            }
679:
680:            protected static void unicodeEscape(Appendable sb, int ch)
681:                    throws IOException {
682:                String str = Integer.toHexString(ch & 0xffff);
683:                switch (str.length()) {
684:                case 1:
685:                    sb.append("\\u000");
686:                    break;
687:                case 2:
688:                    sb.append("\\u00");
689:                    break;
690:                case 3:
691:                    sb.append("\\u0");
692:                    break;
693:                default:
694:                    sb.append("\\u");
695:                    break;
696:                }
697:                sb.append(str);
698:            }
699:
700:        }
701:
702:        class PythonWriter extends JSONWriter {
703:            public PythonWriter(Writer writer, SolrQueryRequest req,
704:                    SolrQueryResponse rsp) {
705:                super (writer, req, rsp);
706:            }
707:
708:            @Override
709:            public void writeNull(String name) throws IOException {
710:                writer.write("None");
711:            }
712:
713:            @Override
714:            public void writeBool(String name, boolean val) throws IOException {
715:                writer.write(val ? "True" : "False");
716:            }
717:
718:            @Override
719:            public void writeBool(String name, String val) throws IOException {
720:                writeBool(name, val.charAt(0) == 't');
721:            }
722:
723:            /* optionally use a unicode python string if necessary */
724:            @Override
725:            public void writeStr(String name, String val, boolean needsEscaping)
726:                    throws IOException {
727:                if (!needsEscaping) {
728:                    writer.write('\'');
729:                    writer.write(val);
730:                    writer.write('\'');
731:                    return;
732:                }
733:
734:                // use python unicode strings...
735:                // python doesn't tolerate newlines in strings in it's eval(), so we must escape them.
736:
737:                StringBuilder sb = new StringBuilder(val.length());
738:                boolean needUnicode = false;
739:
740:                for (int i = 0; i < val.length(); i++) {
741:                    char ch = val.charAt(i);
742:                    switch (ch) {
743:                    case '\'':
744:                    case '\\':
745:                        sb.append('\\');
746:                        sb.append(ch);
747:                        break;
748:                    case '\r':
749:                        sb.append("\\r");
750:                        break;
751:                    case '\n':
752:                        sb.append("\\n");
753:                        break;
754:                    case '\t':
755:                        sb.append("\\t");
756:                        break;
757:                    default:
758:                        // we don't strictly have to escape these chars, but it will probably increase
759:                        // portability to stick to visible ascii
760:                        if (ch < ' ' || ch > 127) {
761:                            unicodeEscape(sb, ch);
762:                            needUnicode = true;
763:                        } else {
764:                            sb.append(ch);
765:                        }
766:                    }
767:                }
768:
769:                writer.write(needUnicode ? "u'" : "'");
770:                writer.append(sb);
771:                writer.write('\'');
772:            }
773:
774:            /*
775:            old version that always used unicode
776:            public void writeStr(String name, String val, boolean needsEscaping) throws IOException {
777:              // use python unicode strings...
778:              // python doesn't tolerate newlines in strings in it's eval(), so we must escape them.
779:              writer.write("u'");
780:              // it might be more efficient to use a stringbuilder or write substrings
781:              // if writing chars to the stream is slow.
782:              if (needsEscaping) {
783:                for (int i=0; i<val.length(); i++) {
784:                  char ch = val.charAt(i);
785:                  switch(ch) {
786:                    case '\'':
787:                    case '\\': writer.write('\\'); writer.write(ch); break;
788:                    case '\r': writer.write("\\r"); break;
789:                    case '\n': writer.write("\\n"); break;
790:                    default:
791:                      // we don't strictly have to escape these chars, but it will probably increase
792:                      // portability to stick to visible ascii
793:                      if (ch<' ' || ch>127) {
794:                        unicodeChar(ch);
795:                      } else {
796:                        writer.write(ch);
797:                      }
798:                  }
799:                }
800:              } else {
801:                writer.write(val);
802:              }
803:              writer.write('\'');
804:            }
805:             */
806:
807:        }
808:
809:        class RubyWriter extends JSONWriter {
810:            public RubyWriter(Writer writer, SolrQueryRequest req,
811:                    SolrQueryResponse rsp) {
812:                super (writer, req, rsp);
813:            }
814:
815:            @Override
816:            public void writeNull(String name) throws IOException {
817:                writer.write("nil");
818:            }
819:
820:            @Override
821:            protected void writeKey(String fname, boolean needsEscaping)
822:                    throws IOException {
823:                writeStr(null, fname, needsEscaping);
824:                writer.write("=>");
825:            }
826:
827:            @Override
828:            public void writeStr(String name, String val, boolean needsEscaping)
829:                    throws IOException {
830:                // Ruby doesn't do unicode escapes... so let the servlet container write raw UTF-8
831:                // bytes into the string.
832:                //
833:                // Use single quoted strings for safety since no evaluation is done within them.
834:                // Also, there are very few escapes recognized in a single quoted string, so
835:                // only escape the backslash and single quote.
836:                writer.write('\'');
837:                // it might be more efficient to use a stringbuilder or write substrings
838:                // if writing chars to the stream is slow.
839:                if (needsEscaping) {
840:                    for (int i = 0; i < val.length(); i++) {
841:                        char ch = val.charAt(i);
842:                        switch (ch) {
843:                        case '\'':
844:                        case '\\':
845:                            writer.write('\\');
846:                            writer.write(ch);
847:                            break;
848:                        default:
849:                            writer.write(ch);
850:                            break;
851:                        }
852:                    }
853:                } else {
854:                    writer.write(val);
855:                }
856:                writer.write('\'');
857:            }
858:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.