KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > rubis > servlets > ServletPrinter


1 package edu.rice.rubis.servlets;
2
3 import java.io.FileReader JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.PrintWriter JavaDoc;
6 import java.net.URLEncoder JavaDoc;
7 import java.sql.Connection JavaDoc;
8 import java.sql.PreparedStatement JavaDoc;
9 import java.sql.ResultSet JavaDoc;
10 import java.util.GregorianCalendar JavaDoc;
11
12 import javax.servlet.http.HttpServletResponse JavaDoc;
13
14 /** In fact, this class is not a servlet itself but it provides
15  * output services to servlets to send back HTML files.
16  * @author <a HREF="mailto:cecchet@rice.edu">Emmanuel Cecchet</a> and <a HREF="mailto:julie.marguerite@inrialpes.fr">Julie Marguerite</a>
17  * @version 1.0
18  */

19
20 public class ServletPrinter
21 {
22   private PrintWriter JavaDoc out;
23   private String JavaDoc servletName;
24   private GregorianCalendar JavaDoc startDate;
25
26   public ServletPrinter(
27     HttpServletResponse JavaDoc toWebServer,
28     String JavaDoc callingServletName)
29   {
30     startDate = new GregorianCalendar JavaDoc();
31     toWebServer.setContentType("text/html");
32     try
33     {
34       out = toWebServer.getWriter();
35     }
36     catch (IOException JavaDoc ioe)
37     {
38       ioe.printStackTrace();
39     }
40     servletName = callingServletName;
41   }
42
43   void printFile(String JavaDoc filename)
44   {
45     FileReader JavaDoc fis = null;
46     try
47     {
48       fis = new FileReader JavaDoc(filename);
49       char[] data = new char[4 * 1024]; // 4K buffer
50
int bytesRead;
51       bytesRead = fis.read(data);
52       while (/*(bytesRead = fis.read(data))*/
53         bytesRead != -1)
54       {
55         out.write(data, 0, bytesRead);
56         bytesRead = fis.read(data);
57       }
58     }
59     catch (Exception JavaDoc e)
60     {
61       out.println("Unable to read file (exception: " + e + ")<br>");
62     }
63     finally
64     {
65       if (fis != null)
66         try
67         {
68           fis.close();
69         }
70         catch (Exception JavaDoc ex)
71         {
72           out.println(
73             "Unable to close the file reader (exception: " + ex + ")<br>");
74         }
75     }
76   }
77
78   void printHTMLheader(String JavaDoc title)
79   {
80     printFile(Config.HTMLFilesPath + "/header.html");
81     out.println("<title>" + title + "</title>");
82   }
83
84   void printHTMLfooter()
85   {
86     GregorianCalendar JavaDoc endDate = new GregorianCalendar JavaDoc();
87
88     out.println(
89       "<br><hr>RUBiS (C) Rice University/INRIA<br><i>Page generated by "
90         + servletName
91         + " in "
92         + TimeManagement.diffTime(startDate, endDate)
93         + "</i><br>");
94     out.println("</body>");
95     out.println("</html>");
96   }
97
98   void printHTML(String JavaDoc msg)
99   {
100     out.println(msg);
101   }
102
103   void printHTMLHighlighted(String JavaDoc msg)
104   {
105     out.println("<TABLE width=\"100%\" bgcolor=\"#CCCCFF\">");
106     out.println(
107       "<TR><TD align=\"center\" width=\"100%\"><FONT size=\"4\" color=\"#000000\"><B>"
108         + msg
109         + "</B></FONT></TD></TR>");
110     out.println("</TABLE><p>");
111   }
112
113   ////////////////////////////////////////
114
// Category related printed functions //
115
////////////////////////////////////////
116

117   void printCategory(String JavaDoc categoryName, int categoryId)
118   {
119     try
120     {
121       out.println(
122         "<a HREF=\"edu.rice.rubis.servlets.SearchItemsByCategory?category="
123           + categoryId
124           + "&categoryName="
125           + URLEncoder.encode(categoryName)
126           + "\">"
127           + categoryName
128           + "</a><br>");
129     }
130     catch (Exception JavaDoc e)
131     {
132       out.println("Unable to print Category (exception: " + e + ")<br>");
133     }
134   }
135
136   /** List all the categories with links to browse items by region */
137   void printCategoryByRegion(String JavaDoc categoryName, int categoryId, int regionId)
138   {
139     try
140     {
141       out.println(
142         "<a HREF=\"edu.rice.rubis.servlets.SearchItemsByRegion?category="
143           + categoryId
144           + "&categoryName="
145           + URLEncoder.encode(categoryName)
146           + "&region="
147           + regionId
148           + "\">"
149           + categoryName
150           + "</a><br>");
151     }
152     catch (Exception JavaDoc e)
153     {
154       out.println("Unable to print Category (exception: " + e + ")<br>");
155     }
156   }
157
158   /** Lists all the categories and links to the sell item page*/
159   void printCategoryToSellItem(String JavaDoc categoryName, int categoryId, int userId)
160   {
161     try
162     {
163       out.println(
164         "<a HREF=\"edu.rice.rubis.servlets.SellItemForm?category="
165           + categoryId
166           + "&user="
167           + userId
168           + "\">"
169           + categoryName
170           + "</a><br>");
171     }
172     catch (Exception JavaDoc e)
173     {
174       out.println("Unable to print Category (exception: " + e + ")<br>");
175     }
176   }
177
178   //////////////////////////////////////
179
// Region related printed functions //
180
//////////////////////////////////////
181

182   void printRegion(String JavaDoc regionName)
183   {
184     try
185     {
186       out.println(
187         "<a HREF=\"edu.rice.rubis.servlets.BrowseCategories?region="
188           + URLEncoder.encode(regionName)
189           + "\">"
190           + regionName
191           + "</a><br>");
192     }
193     catch (Exception JavaDoc e)
194     {
195       out.println("Unable to print Region (exception: " + e + ")<br>");
196     }
197   }
198
199   //////////////////////////////////////
200
// Item related printed functions //
201
//////////////////////////////////////
202

203   void printItemHeader()
204   {
205     out.println(
206       "<TABLE border=\"1\" summary=\"List of items\">"
207         + "<THEAD>"
208         + "<TR><TH>Designation<TH>Price<TH>Bids<TH>End Date<TH>Bid Now"
209         + "<TBODY>");
210   }
211
212   void printItem(
213     String JavaDoc itemName,
214     int itemId,
215     float maxBid,
216     int nbOfBids,
217     String JavaDoc endDate)
218   {
219     try
220     {
221       out.println(
222         "<TR><TD><a HREF=\"edu.rice.rubis.servlets.ViewItem?itemId="
223           + itemId
224           + "\">"
225           + itemName
226           + "<TD>"
227           + maxBid
228           + "<TD>"
229           + nbOfBids
230           + "<TD>"
231           + endDate
232           + "<TD><a HREF=\"edu.rice.rubis.servlets.PutBidAuth?itemId="
233           + itemId
234           + "\"><IMG SRC=\"/rubis_servlets/bid_now.jpg\" height=22 width=90></a>");
235     }
236     catch (Exception JavaDoc e)
237     {
238       out.println("Unable to print Item (exception: " + e + ")<br>");
239     }
240   }
241
242   void printItemFooter()
243   {
244     out.println("</TABLE>");
245   }
246
247   void printItemFooter(String JavaDoc URLprevious, String JavaDoc URLafter)
248   {
249     out.println("</TABLE>\n");
250     out.println(
251       "<p><CENTER>\n"
252         + URLprevious
253         + "\n&nbsp&nbsp&nbsp"
254         + URLafter
255         + "\n</CENTER>\n");
256   }
257
258   /**
259    * Print the full description of an item and the bidding option if userId>0.
260    */

261   void printItemDescription(
262     int itemId,
263     String JavaDoc itemName,
264     String JavaDoc description,
265     float initialPrice,
266     float reservePrice,
267     float buyNow,
268     int quantity,
269     float maxBid,
270     int nbOfBids,
271     String JavaDoc sellerName,
272     int sellerId,
273     String JavaDoc startDate,
274     String JavaDoc endDate,
275     int userId,
276     Connection JavaDoc conn)
277   {
278     PreparedStatement JavaDoc stmt = null;
279     try
280     {
281       String JavaDoc firstBid;
282
283       // Compute the current price of the item
284
if (maxBid == 0)
285       {
286         firstBid = "none";
287       }
288       else
289       {
290         if (quantity > 1)
291         {
292           try
293           {
294             /* Get the qty max first bids and parse bids in this order
295                until qty is reached. The bid that reaches qty is the
296                current minimum bid. */

297
298             stmt =
299               conn.prepareStatement(
300                 "SELECT id,qty,max_bid FROM bids WHERE item_id=? ORDER BY bid DESC LIMIT ?");
301             stmt.setInt(1, itemId);
302             stmt.setInt(2, quantity);
303             ResultSet JavaDoc rs = stmt.executeQuery();
304             if (rs.first())
305             {
306               int numberOfItems = 0;
307               int qty;
308               do
309               {
310                 qty = rs.getInt("qty");
311                 numberOfItems = numberOfItems + qty;
312                 if (numberOfItems >= quantity)
313                 {
314                   maxBid = rs.getFloat("max_bid");
315                   ;
316                   break;
317                 }
318               }
319               while (rs.next());
320             }
321           }
322           catch (Exception JavaDoc e)
323           {
324             printHTML("Problem while computing current bid: " + e + "<br>");
325             return;
326           }
327         }
328         Float JavaDoc foo = new Float JavaDoc(maxBid);
329         firstBid = foo.toString();
330       }
331       if (userId > 0)
332       {
333         printHTMLheader("RUBiS: Bidding\n");
334         printHTMLHighlighted("You are ready to bid on: " + itemName);
335       }
336       else
337       {
338         printHTMLheader("RUBiS: Viewing " + itemName + "\n");
339         printHTMLHighlighted(itemName);
340       }
341       out.println(
342         "<TABLE>\n"
343           + "<TR><TD>Currently<TD><b><BIG>"
344           + maxBid
345           + "</BIG></b>\n");
346       // Check if the reservePrice has been met (if any)
347
if (reservePrice > 0)
348       { // Has the reserve price been met ?
349
if (maxBid >= reservePrice)
350           out.println("(The reserve price has been met)\n");
351         else
352           out.println("(The reserve price has NOT been met)\n");
353       }
354       out.println(
355         "<TR><TD>Quantity<TD><b><BIG>"
356           + quantity
357           + "</BIG></b>\n"
358           + "<TR><TD>First bid<TD><b><BIG>"
359           + firstBid
360           + "</BIG></b>\n"
361           + "<TR><TD># of bids<TD><b><BIG>"
362           + nbOfBids
363           + "</BIG></b> (<a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewBidHistory?itemId="
364           + itemId
365           + "\">bid history</a>)\n"
366           + "<TR><TD>Seller<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewUserInfo?userId="
367           + sellerId
368           + "\">"
369           + sellerName
370           + "</a> (<a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.PutCommentAuth?to="
371           + sellerId
372           + "&itemId="
373           + itemId
374           + "\">Leave a comment on this user</a>)\n"
375           + "<TR><TD>Started<TD>"
376           + startDate
377           + "\n"
378           + "<TR><TD>Ends<TD>"
379           + endDate
380           + "\n"
381           + "</TABLE>");
382       // Can the user buy this item now ?
383
if (buyNow > 0)
384         out.println(
385           "<p><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.BuyNowAuth?itemId="
386             + itemId
387             + "\">"
388             + "<IMG SRC=\"/rubis_servlets/buy_it_now.jpg\" height=22 width=150></a>"
389             + " <BIG><b>You can buy this item right now for only $"
390             + buyNow
391             + "</b></BIG><br><p>\n");
392
393       if (userId <= 0)
394       {
395         out.println(
396           "<a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.PutBidAuth?itemId="
397             + itemId
398             + "\"><IMG SRC=\"/rubis_servlets/bid_now.jpg\" height=22 width=90> on this item</a>\n");
399       }
400
401       printHTMLHighlighted("Item description");
402       out.println(description);
403       out.println("<br><p>\n");
404
405       if (userId > 0)
406       {
407         printHTMLHighlighted("Bidding");
408         float minBid = maxBid + 1;
409         printHTML(
410           "<form action=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.StoreBid\" method=POST>\n"
411             + "<input type=hidden name=minBid value="
412             + minBid
413             + ">\n"
414             + "<input type=hidden name=userId value="
415             + userId
416             + ">\n"
417             + "<input type=hidden name=itemId value="
418             + itemId
419             + ">\n"
420             + "<input type=hidden name=maxQty value="
421             + quantity
422             + ">\n"
423             + "<center><table>\n"
424             + "<tr><td>Your bid (minimum bid is "
425             + minBid
426             + "):</td>\n"
427             + "<td><input type=text size=10 name=bid></td></tr>\n"
428             + "<tr><td>Your maximum bid:</td>\n"
429             + "<td><input type=text size=10 name=maxBid></td></tr>\n");
430         if (quantity > 1)
431           printHTML(
432             "<tr><td>Quantity:</td>\n"
433               + "<td><input type=text size=5 name=qty></td></tr>\n");
434         else
435           printHTML("<input type=hidden name=qty value=1>\n");
436         printHTML("</table><p><input type=submit value=\"Bid now!\"></center><p>\n");
437       }
438     }
439     catch (Exception JavaDoc e)
440     {
441       out.println(
442         "Unable to print Item description (exception: " + e + ")<br>\n");
443     }
444   }
445
446   ////////////////////////////////////////
447
// About me related printed functions //
448
////////////////////////////////////////
449

450   void printUserBidsHeader()
451   {
452     printHTMLHighlighted("<p><h3>Items you have bid on.</h3>\n");
453     out.println(
454       "<TABLE border=\"1\" summary=\"Items You've bid on\">\n"
455         + "<THEAD>\n"
456         + "<TR><TH>Designation<TH>Initial Price<TH>Current price<TH>Your max bid<TH>Quantity"
457         + "<TH>Start Date<TH>End Date<TH>Seller<TH>Put a new bid\n"
458         + "<TBODY>\n");
459   }
460
461   void printItemUserHasBidOn(
462     int itemId,
463     String JavaDoc itemName,
464     float initialPrice,
465     int quantity,
466     String JavaDoc startDate,
467     String JavaDoc endDate,
468     int sellerId,
469     String JavaDoc sellerName,
470     float currentPrice,
471     float maxBid,
472     String JavaDoc username,
473     String JavaDoc password)
474   {
475     try
476     {
477       out.println(
478         "<TR><TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewItem?itemId="
479           + itemId
480           + "\">"
481           + itemName
482           + "<TD>"
483           + initialPrice
484           + "<TD>"
485           + currentPrice
486           + "<TD>"
487           + maxBid
488           + "<TD>"
489           + quantity
490           + "<TD>"
491           + startDate
492           + "<TD>"
493           + endDate
494           + "<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewUserInfo?userId="
495           + sellerId
496           + "\">"
497           + sellerName
498           + "<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.PutBid?itemId="
499           + itemId
500           + "&nickname="
501           + username
502           + "&password="
503           + password
504           + "\"><IMG SRC=\"/rubis_servlets/bid_now.jpg\" height=22 width=90></a>\n");
505     }
506     catch (Exception JavaDoc e)
507     {
508       out.println("Unable to print Item (exception: " + e + ")<br>\n");
509     }
510   }
511
512   void printUserWonItemHeader()
513   {
514     printHTML("<br>");
515     printHTMLHighlighted("<p><h3>Items you won in the past 30 days.</h3>\n");
516     out.println(
517       "<TABLE border=\"1\" summary=\"List of items\">\n"
518         + "<THEAD>\n"
519         + "<TR><TH>Designation<TH>Price you bought it<TH>Seller"
520         + "<TBODY>\n");
521   }
522
523   void printUserWonItem(
524     int itemId,
525     String JavaDoc itemName,
526     float currentPrice,
527     int sellerId,
528     String JavaDoc sellerName)
529   {
530     try
531     {
532       out.println(
533         "<TR><TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewItem?itemId="
534           + itemId
535           + "\">"
536           + itemName
537           + "</a>\n"
538           + "<TD>"
539           + currentPrice
540           + "\n"
541           + "<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewUserInfo?userId="
542           + sellerId
543           + "\">"
544           + sellerName
545           + "</a>\n");
546     }
547     catch (Exception JavaDoc e)
548     {
549       out.println("Unable to print Item (exception: " + e + ")<br>\n");
550     }
551   }
552
553   void printUserBoughtItemHeader()
554   {
555     printHTML("<br>");
556     printHTMLHighlighted("<p><h3>Items you bouhgt in the past 30 days.</h3>\n");
557     out.println(
558       "<TABLE border=\"1\" summary=\"List of items\">\n"
559         + "<THEAD>\n"
560         + "<TR><TH>Designation<TH>Quantity<TH>Price you bought it<TH>Seller"
561         + "<TBODY>\n");
562   }
563
564   void printUserBoughtItem(
565     int itemId,
566     String JavaDoc itemName,
567     float buyNow,
568     int quantity,
569     int sellerId,
570     String JavaDoc sellerName)
571   {
572     try
573     {
574       out.println(
575         "<TR><TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewItem?itemId="
576           + itemId
577           + "\">"
578           + itemName
579           + "</a>\n"
580           + "<TD>"
581           + quantity
582           + "\n"
583           + "<TD>"
584           + buyNow
585           + "\n"
586           + "<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.beans.servlets.ViewUserInfo?userId="
587           + sellerId
588           + "\">"
589           + sellerName
590           + "</a>\n");
591     }
592     catch (Exception JavaDoc e)
593     {
594       out.println("Unable to print Item (exception: " + e + ")<br>\n");
595     }
596   }
597
598   void printSellHeader(String JavaDoc title)
599   {
600     printHTMLHighlighted("<p><h3>" + title + "</h3>\n");
601     out.println(
602       "<TABLE border=\"1\" summary=\"List of items\">\n"
603         + "<THEAD>\n"
604         + "<TR><TH>Designation<TH>Initial Price<TH>Current price<TH>Quantity<TH>ReservePrice<TH>Buy Now"
605         + "<TH>Start Date<TH>End Date\n"
606         + "<TBODY>\n");
607   }
608
609   void printSell(
610     int itemId,
611     String JavaDoc itemName,
612     float initialPrice,
613     float reservePrice,
614     int quantity,
615     float buyNow,
616     String JavaDoc startDate,
617     String JavaDoc endDate,
618     float currentPrice)
619   {
620     try
621     {
622       out.println(
623         "<TR><TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewItem?itemId="
624           + itemId
625           + "\">"
626           + itemName
627           + "<TD>"
628           + initialPrice
629           + "<TD>"
630           + currentPrice
631           + "<TD>"
632           + quantity
633           + "<TD>"
634           + reservePrice
635           + "<TD>"
636           + buyNow
637           + "<TD>"
638           + startDate
639           + "<TD>"
640           + endDate
641           + "\n");
642     }
643     catch (Exception JavaDoc e)
644     {
645       out.println("Unable to print Item (exception: " + e + ")<br>\n");
646     }
647   }
648
649   ///////////////////////////////////////
650
// Buy now related printed functions //
651
///////////////////////////////////////
652

653   /**
654    * Print the full description of an item and the buy now option
655    *
656    * @param item an <code>Item</code> value
657    * @param userId an authenticated user id
658    */

659   void printItemDescriptionToBuyNow(
660     int itemId,
661     String JavaDoc itemName,
662     String JavaDoc description,
663     float buyNow,
664     int quantity,
665     int sellerId,
666     String JavaDoc sellerName,
667     String JavaDoc startDate,
668     String JavaDoc endDate,
669     int userId)
670   {
671     try
672     {
673
674       printHTMLheader("RUBiS: Buy Now");
675       printHTMLHighlighted("You are ready to buy this item: " + itemName);
676
677       out.println(
678         "<TABLE>\n"
679           + "<TR><TD>Quantity<TD><b><BIG>"
680           + quantity
681           + "</BIG></b>\n"
682           + "<TR><TD>Seller<TD><a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.ViewUserInfo?userId="
683           + sellerId
684           + "\">"
685           + sellerName
686           + "</a> (<a HREF=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.PutCommentAuth?to="
687           + sellerId
688           + "&itemId="
689           + itemId
690           + "\">Leave a comment on this user</a>)\n"
691           + "<TR><TD>Started<TD>"
692           + startDate
693           + "\n"
694           + "<TR><TD>Ends<TD>"
695           + endDate
696           + "\n"
697           + "</TABLE>");
698
699       printHTMLHighlighted("Item description");
700       out.println(description);
701       out.println("<br><p>\n");
702
703       printHTMLHighlighted("Buy Now");
704       printHTML(
705         "<form action=\"/rubis_servlets/servlet/edu.rice.rubis.servlets.StoreBuyNow\" method=POST>\n"
706           + "<input type=hidden name=userId value="
707           + userId
708           + ">\n"
709           + "<input type=hidden name=itemId value="
710           + itemId
711           + ">\n"
712           + "<input type=hidden name=maxQty value="
713           + quantity
714           + ">\n");
715       if (quantity > 1)
716         printHTML(
717           "<center><table><tr><td>Quantity:</td>\n"
718             + "<td><input type=text size=5 name=qty></td></tr></table></center>\n");
719       else
720         printHTML("<input type=hidden name=qty value=1>\n");
721       printHTML("<p><center><input type=submit value=\"Buy now!\"></center><p>\n");
722     }
723     catch (Exception JavaDoc e)
724     {
725       out.println(
726         "Unable to print Item description (exception: " + e + ")<br>\n");
727     }
728   }
729
730   ///////////////////////////////////
731
// Bid related printed functions //
732
///////////////////////////////////
733

734   void printBidHistoryHeader()
735   {
736     out.println(
737       "<TABLE border=\"1\" summary=\"List of bids\">"
738         + "<THEAD>"
739         + "<TR><TH>User ID<TH>Bid amount<TH>Date of bid"
740         + "<TBODY>");
741   }
742
743   void printBidHistoryFooter()
744   {
745     out.println("</TBODY></TABLE>");
746   }
747
748   void printBidHistory(int userId, String JavaDoc bidderName, float bid, String JavaDoc date)
749   {
750     try
751     {
752       out.println(
753         "<TR><TD><a HREF=\"edu.rice.rubis.servlets.ViewUserInfo?userId="
754           + userId
755           + "\">"
756           + bidderName
757           + "<TD>"
758           + bid
759           + "<TD>"
760           + date);
761     }
762     catch (Exception JavaDoc e)
763     {
764       out.println("Unable to print Bid (exception: " + e + ")<br>");
765     }
766   }
767
768   /////////////////////////////////////////
769
// Comment related printed functions //
770
/////////////////////////////////////////
771

772   void printCommentHeader()
773   {
774     out.println("<DL>");
775   }
776
777   void printComment(String JavaDoc userName, int userId, String JavaDoc date, String JavaDoc comment)
778   {
779     try
780     {
781       out.println(
782         "<DT><b><BIG><a HREF=\"edu.rice.rubis.servlets.ViewUserInfo?userId="
783           + userId
784           + "\">"
785           + userName
786           + "</a></BIG></b>"
787           + " wrote the "
788           + date
789           + "<DD><i>"
790           + comment
791           + "</i><p>");
792     }
793     catch (Exception JavaDoc e)
794     {
795       out.println("Unable to print Comment (exception: " + e + ")<br>");
796     }
797   }
798
799   void printCommentFooter()
800   {
801     out.println("</DL>");
802   }
803
804 }
805
Popular Tags