Persoenliche Mediazentrale
undisclosed
2023-01-21 43d323fa088153082a33966b19d81e9169cc7bf2
commit | author | age
8d7d35 1 /*
94b1c2 2   Tango - Personal Media Center
8d7d35 3   Copyright (C) 2021  Ulrich Hilger
U 4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as
7   published by the Free Software Foundation, either version 3 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
94b1c2 18 package de.uhilger.tango.api;
8d7d35 19
e60cff 20 import com.google.gson.Gson;
43d323 21 import com.sun.net.httpserver.Headers;
8d7d35 22 import com.sun.net.httpserver.HttpExchange;
94b1c2 23 import de.uhilger.tango.Server;
U 24 import de.uhilger.tango.entity.Abspielliste;
25 import de.uhilger.tango.entity.Entity;
26 import de.uhilger.tango.entity.Titel;
27 import de.uhilger.tango.store.FileStorage;
43d323 28 import java.io.File;
8d7d35 29 import java.io.IOException;
1bf4f6 30 import java.util.List;
e60cff 31 import java.util.logging.Logger;
8d7d35 32
U 33 /**
34  * Der ListHandler bearbeitet HTTP-Anfragen zu Abspiellisten
35  * 
36  * GET /mz/api/alist/[pl-name]          die Titel-Objekte der Liste [pl-name] liefern
37  * PUT /mz/api/alist/[pl-name]          den Titel im Body anfuegen an die Liste [pl-name]
38  * PUT /mz/api/alist/[pl-name]/[nr]     an der Position nr der Liste [pl-name] den Titel im Body einfuegen
1bf4f6 39  * PUT /mz/api/alist/[pl-name]/[nrVon]/[nrNach]   den Titel von seiner aktuellen Position an eine 
U 40  *                                                 andere Position der Liste [pl-name] verschieben
43d323 41  * GET /mz/api/alist/[pl-name]/m3u
8d7d35 42  * DELETE /mz/api/alist/[pl-name]/[nr]  den Titel an der Position [nr] aus der Liste [pl-name] entfernen  
095119 43  * DELETE /mz/api/alist/[pl-name]/alle  alle Titel aus der Liste [pl-name] entfernen  
792b21 44  * 
U 45  * TODO (2.1.2023):
46  * - Liste ab Titel spielen
47  * - Ganzes Album der Liste hinzufuegen
8d7d35 48  *
U 49  * @author Ulrich Hilger
50  * @version 1, 8.4.2021
51  */
52 public class ListHandler extends AbstractHandler {
e60cff 53   
U 54   private static final Logger logger = Logger.getLogger(ListHandler.class.getName());
095119 55   
U 56   public static final String ALLE_TITEL = "alle";
f70acb 57   
U 58   private String conf;
59   
60   public ListHandler(String conf) {
61     this.conf = conf;
62   }
8d7d35 63
U 64   @Override
65   protected String get(HttpExchange e) {
e60cff 66     String path = e.getRequestURI().toString();
0e9cd3 67     String[] elems = path.split(Server.SLASH);
43d323 68     if(elems.length > 5) {
U 69       if(elems[5].endsWith("m3u")) {
70         Headers headers = e.getResponseHeaders();
71         headers.add("Content-Type", "application/m3u");
72         return getM3u(e, elems[4]);
73       } else {
74         return "ungueltig";
75       }
76     } else {
77       String plname = elems[elems.length - 1];
78       FileStorage fs = new FileStorage(conf);
79       String json = fs.readJson(FileStorage.ST_ABSPIELLISTE, plname);
80       return embedInCustomType(json, FileStorage.ST_ABSPIELLISTE);
81     }
82   }
83   
84   private String getM3u(HttpExchange e, String plname) {
85     StringBuilder sb = new StringBuilder();
86     FileStorage fs = new FileStorage(conf);    
87     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
88     if (entity instanceof Abspielliste) {
89       Abspielliste liste = (Abspielliste) entity;
90       List<Titel> titelListe = liste.getTitel();
91       
92       for(Titel titel : titelListe) {
93         
94         sb.append("http://hsrv:9090/tango");
95         sb.append(titel.getKatalogUrl());
96         sb.append(titel.getPfad());
97         sb.append(titel.getName());
98         sb.append("\n");
99       }
100     }
101     return sb.toString();
8d7d35 102   }
U 103
104   @Override
105   protected String put(HttpExchange e) throws IOException {
e60cff 106     String path = e.getRequestURI().toString();
0e9cd3 107     String[] elems = path.split(Server.SLASH);
e60cff 108     String response = "ListHandler.put: ungueltiger URL";
U 109     switch(elems.length) {
8e2578 110       case 5: // ohne nr am Ende
e60cff 111         response = addTitel(e, elems[4]);
U 112         break;
113         
114       case 6:
1bf4f6 115         response = insertTitel(e, elems[4], Integer.parseInt(elems[5]));
e60cff 116         break;
1bf4f6 117         
U 118       case 7:
119         response = moveTitel(e, elems[4], Integer.parseInt(elems[5]), Integer.parseInt(elems[6]));
120         break;
121     }
122     return response;
123   }
124   
125   /**
126    * Den Titel im Body von seiner aktuellen Position an die angegebene 
127    * Position setzen. Der Titel an der angegebenen Position rueckt nach 
128    * unten.
129    * 
130    * Annahme: Die Abspielliste enthaelt keine Titel mehrfach.
131    * 
132    * @param e
133    * @param plname
134    * @param zielPos
135    * @return
136    * @throws IOException 
137    */
138   private String moveTitel(HttpExchange e, String plname, int pos, int zielPos) throws IOException {
139     FileStorage fs = new FileStorage(conf);
140     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
141     String response = "Titel konnte nicht verschoben werden.";
142     if(entity instanceof Abspielliste) {
143       if(pos < zielPos) {
144         --zielPos;
145       }
146       Abspielliste aliste = (Abspielliste) entity;
147       List<Titel> liste = aliste.getTitel();
148       Titel t = liste.get(pos);
149       liste.remove(pos);
150       liste.add(zielPos, t);
151       fs.write(aliste, true);
152       response = "Titel " + t.getName() + " der Liste " + aliste.getName() + 
153               " an Position " + zielPos + " verschoben.";
154     }
155     return response;
156   }
157   
158   /**
159    * Den Titel im Body an Position anPos einfuegen. Der Titel an anPos 
160    * rueckt nach unten.
161    * 
162    * @param e
163    * @param plname
164    * @param anPos
165    * @return
166    * @throws IOException 
167    */
168   private String insertTitel(HttpExchange e, String plname, int anPos) throws IOException {
169     FileStorage fs = new FileStorage(conf);
170     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
171     String response = "Titel konnte nicht hinzugefuegt werden.";
172     if(entity instanceof Abspielliste) {
173       Abspielliste aliste = (Abspielliste) entity;
174       String titelJson = bodyLesen(e);
175       Gson gson = new Gson();
176       Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
177       if(o instanceof Titel) {
178         Titel titel = (Titel) o;
179         aliste.putTitel(titel, anPos);
180         fs.write(aliste, true);
181         response = "Titel " + titel.getName() + " der Liste " + aliste.getName() + 
182                 " an Position " + anPos + " hinzugefuegt.";
183       }
e60cff 184     }
U 185     return response;
186   }
187   
188   private String addTitel(HttpExchange e, String plname) throws IOException {
f70acb 189     FileStorage fs = new FileStorage(conf);
e60cff 190     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
U 191     String response = "Titel konnte nicht hinzugefuegt werden.";
192     if(entity instanceof Abspielliste) {
193       Abspielliste aliste = (Abspielliste) entity;
194       String titelJson = bodyLesen(e);
195       Gson gson = new Gson();
196       Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
197       if(o instanceof Titel) {
198         Titel titel = (Titel) o;
199         aliste.addTitel(titel);
200         fs.write(aliste, true);
201         response = "Titel " + titel.getName() + " der Liste " + aliste.getName() + " hinzugefuegt.";
202       }
203     }
204     return response;
8d7d35 205   }
U 206
172013 207   // DELETE /mz/api/alist/[pl-name]/[nr]  den Titel an der Position [nr] aus der Liste [pl-name] entfernen  
8d7d35 208   @Override
U 209   protected boolean delete(HttpExchange e) {
172013 210     String path = e.getRequestURI().toString();
U 211     String[] elems = path.split(Server.SLASH);
5f7e0b 212     String listName = elems[elems.length - 2];
f70acb 213     FileStorage fs = new FileStorage(conf);
172013 214     Entity entity = fs.read(Abspielliste.class.getSimpleName(), listName);
U 215     if(entity instanceof Abspielliste) {
216       Abspielliste liste = (Abspielliste) entity;
095119 217       String titelStr = elems[elems.length-1];
U 218       if(titelStr.equalsIgnoreCase(ALLE_TITEL)) {
219         liste.getTitel().clear();
220       } else {
221         liste.getTitel().remove(Integer.parseInt(elems[elems.length-1]));
222       }
172013 223       fs.write(liste, true);
U 224       return true;
225     } else {
226       return false;
227     }
8d7d35 228   }
U 229   
230 }