Add comparator for parties to the sort filter.
[demoscenemusic.git] / src / main / java / net / pterodactylus / demoscenemusic / core / TemplateServlet.java
1 /*
2  * DemosceneMusic - TemplateServlet.java - Copyright © 2012 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.demoscenemusic.core;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.io.Reader;
26 import java.io.UnsupportedEncodingException;
27 import java.lang.reflect.InvocationTargetException;
28 import java.net.URISyntaxException;
29 import java.util.Comparator;
30 import java.util.Enumeration;
31 import java.util.HashMap;
32 import java.util.Map;
33
34 import javax.servlet.ServletConfig;
35 import javax.servlet.ServletException;
36 import javax.servlet.http.HttpServlet;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39
40 import net.pterodactylus.demoscenemusic.data.Artist;
41 import net.pterodactylus.demoscenemusic.data.DefaultParty;
42 import net.pterodactylus.demoscenemusic.data.Party;
43 import net.pterodactylus.demoscenemusic.data.Properties;
44 import net.pterodactylus.demoscenemusic.data.Style;
45 import net.pterodactylus.demoscenemusic.data.Track;
46 import net.pterodactylus.demoscenemusic.data.TrackDerivative;
47 import net.pterodactylus.demoscenemusic.data.User;
48 import net.pterodactylus.demoscenemusic.page.ServletRequest;
49 import net.pterodactylus.demoscenemusic.template.ConciseNumberFilter;
50 import net.pterodactylus.demoscenemusic.template.DurationFilter;
51 import net.pterodactylus.demoscenemusic.template.PropertiesAccessor;
52 import net.pterodactylus.demoscenemusic.template.TrackDerivativeAccessor;
53 import net.pterodactylus.demoscenemusic.template.UserAccessor;
54 import net.pterodactylus.util.io.Closer;
55 import net.pterodactylus.util.io.StreamCopier;
56 import net.pterodactylus.util.template.ClassPathTemplateProvider;
57 import net.pterodactylus.util.template.CollectionSortFilter;
58 import net.pterodactylus.util.template.HtmlFilter;
59 import net.pterodactylus.util.template.MatchFilter;
60 import net.pterodactylus.util.template.ReflectionAccessor;
61 import net.pterodactylus.util.template.Template;
62 import net.pterodactylus.util.template.TemplateContextFactory;
63 import net.pterodactylus.util.template.TemplateParser;
64 import net.pterodactylus.util.web.Header;
65 import net.pterodactylus.util.web.Page;
66 import net.pterodactylus.util.web.Response;
67
68 /**
69  * TODO
70  *
71  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
72  */
73 public class TemplateServlet extends HttpServlet {
74
75         private Core core;
76
77         private final TemplateContextFactory templateContextFactory = new TemplateContextFactory();
78
79         private final Map<String, Page<ServletRequest>> pages = new HashMap<String, Page<ServletRequest>>();
80
81         //
82         // SERVLET METHODS
83         //
84
85         /**
86          * {@inheritDoc}
87          */
88         @Override
89         public void init(ServletConfig config) throws ServletException {
90                 super.init(config);
91                 core = (Core) config.getServletContext().getAttribute("core");
92
93                 templateContextFactory.addAccessor(Object.class, new ReflectionAccessor());
94                 templateContextFactory.addAccessor(User.class, new UserAccessor());
95                 templateContextFactory.addAccessor(Properties.class, new PropertiesAccessor());
96                 templateContextFactory.addAccessor(TrackDerivative.class, new TrackDerivativeAccessor());
97
98                 templateContextFactory.addFilter("html", new HtmlFilter());
99                 CollectionSortFilter sortFilter = new CollectionSortFilter();
100                 sortFilter.addComparator(Artist.class, new Comparator<Artist>() {
101
102                         @Override
103                         public int compare(Artist leftArtist, Artist rightArtist) {
104                                 return leftArtist.getName().compareToIgnoreCase(rightArtist.getName());
105                         }
106
107                 });
108                 sortFilter.addComparator(Track.class, new Comparator<Track>() {
109
110                         @Override
111                         public int compare(Track leftTrack, Track rightTrack) {
112                                 return leftTrack.getName().compareToIgnoreCase(rightTrack.getName());
113                         }
114
115                 });
116                 sortFilter.addComparator(Style.class, new Comparator<Style>() {
117
118                         @Override
119                         public int compare(Style leftStyle, Style rightStyle) {
120                                 return leftStyle.getName().compareToIgnoreCase(rightStyle.getName());
121                         }
122
123                 });
124                 sortFilter.addComparator(Party.class, DefaultParty.NAME_YEAR_COMPARATOR);
125                 templateContextFactory.addFilter("sort", sortFilter);
126                 templateContextFactory.addFilter("matches", new MatchFilter());
127                 templateContextFactory.addFilter("time", new DurationFilter());
128                 templateContextFactory.addFilter("concise", new ConciseNumberFilter());
129
130                 templateContextFactory.addTemplateObject("core", core);
131                 templateContextFactory.addTemplateObject("dataManager", core.getDataManager());
132
133                 templateContextFactory.addProvider(new ClassPathTemplateProvider(getClass(), "/templates/"));
134
135                 for (@SuppressWarnings("rawtypes")
136                 Enumeration parameterNames = config.getInitParameterNames(); parameterNames.hasMoreElements();) {
137                         String pageName = (String) parameterNames.nextElement();
138                         Template template = getTemplate(pageName);
139                         String pageClassName = config.getInitParameter(pageName);
140                         try {
141                                 Class<?> pageClass = Class.forName(pageClassName);
142                                 @SuppressWarnings("unchecked")
143                                 Page<ServletRequest> page = (Page<ServletRequest>) pageClass.getConstructor(Core.class, TemplateContextFactory.class, Template.class).newInstance(core, templateContextFactory, template);
144                                 pages.put(pageName, page);
145                         } catch (ClassNotFoundException cnfe1) {
146                                 cnfe1.printStackTrace();
147                         } catch (IllegalArgumentException iae1) {
148                                 iae1.printStackTrace();
149                         } catch (SecurityException se1) {
150                                 se1.printStackTrace();
151                         } catch (InstantiationException ie1) {
152                                 ie1.printStackTrace();
153                         } catch (IllegalAccessException iae1) {
154                                 iae1.printStackTrace();
155                         } catch (InvocationTargetException ite1) {
156                                 ite1.printStackTrace();
157                         } catch (NoSuchMethodException nsme1) {
158                                 nsme1.printStackTrace();
159                         }
160                 }
161         }
162
163         /**
164          * {@inheritDoc}
165          */
166         @Override
167         protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException {
168                 request.setCharacterEncoding("UTF-8");
169                 String path = request.getPathInfo();
170                 if (path.startsWith("/")) {
171                         path = path.substring(1);
172                 }
173                 if ((path.length() == 0) || (path.endsWith("/"))) {
174                         path += "index";
175                 }
176                 Page<ServletRequest> page = pages.get(path);
177                 if (page != null) {
178                         ServletRequest servletRequest;
179                         try {
180                                 servletRequest = new ServletRequest(request, this);
181                         } catch (URISyntaxException use1) {
182                                 throw new IOException("Could not create URI from " + request.getRequestURI(), use1);
183                         }
184                         ByteArrayOutputStream responseOutputBuffer = new ByteArrayOutputStream();
185                         Response response = new Response(responseOutputBuffer);
186                         response = page.handleRequest(servletRequest, response);
187                         for (Header header : response.getHeaders()) {
188                                 for (String value : header) {
189                                         httpServletResponse.addHeader(header.getName(), value);
190                                 }
191                         }
192                         httpServletResponse.setContentType(response.getContentType());
193                         httpServletResponse.setStatus(response.getStatusCode());
194                         StreamCopier.copy(new ByteArrayInputStream(responseOutputBuffer.toByteArray()), httpServletResponse.getOutputStream());
195                         return;
196                 }
197         }
198
199         /**
200          * {@inheritDoc}
201          */
202         @Override
203         protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
204                 doGet(httpServletRequest, httpServletResponse);
205         }
206
207         //
208         // PRIVATE METHODS
209         //
210
211         private Template getTemplate(String pageName) {
212                 InputStream templateInputStream = getClass().getResourceAsStream("/templates/" + pageName);
213                 if (templateInputStream == null) {
214                         return null;
215                 }
216                 Reader templateReader = null;
217                 try {
218                         templateReader = new InputStreamReader(templateInputStream, "UTF-8");
219                         return TemplateParser.parse(templateReader);
220                 } catch (UnsupportedEncodingException uee1) {
221                         /* can not happen. */
222                         throw new RuntimeException("Could not parse templates!", uee1);
223                 } finally {
224                         Closer.close(templateReader);
225                         Closer.close(templateInputStream);
226                 }
227         }
228
229 }