Persoenliche Mediazentrale
undisclosed
2023-01-23 03b95f100b605458e5bf2995e955882d9aa51868
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;
8d7d35 28 import java.io.IOException;
1bf4f6 29 import java.util.List;
e60cff 30 import java.util.logging.Logger;
8d7d35 31
U 32 /**
33  * Der ListHandler bearbeitet HTTP-Anfragen zu Abspiellisten
34  * 
03b95f 35  * GET /tango/api/alist/[pl-name]          die Titel-Objekte der Liste [pl-name] liefern
U 36  * GET /tango/api/alist/[pl-name]/m3u      eine einfache Playlist im M3U-Format ausgeben
37  * GET /tango/api/alist/[pl-name]/[nr]     den Titel mit der Nummer [nr] abrufen
a6081c 38  * 
03b95f 39  * PUT /tango/api/alist/[pl-name]          den Titel im Body anfuegen an die Liste [pl-name]
U 40  * PUT /tango/api/alist/[pl-name]/[nr]     an der Position nr der Liste [pl-name] den Titel im Body einfuegen
41  * PUT /tango/api/alist/[pl-name]/[nrVon]/[nrNach]   den Titel von seiner aktuellen Position an eine 
1bf4f6 42  *                                                 andere Position der Liste [pl-name] verschieben
03b95f 43  * DELETE /tango/api/alist/[pl-name]/[nr]  den Titel an der Position [nr] aus der Liste [pl-name] entfernen  
U 44  * DELETE /tango/api/alist/[pl-name]/alle  alle Titel aus der Liste [pl-name] entfernen  
792b21 45  * 
U 46  * TODO (2.1.2023):
47  * - Liste ab Titel spielen
48  * - Ganzes Album der Liste hinzufuegen
8d7d35 49  *
U 50  * @author Ulrich Hilger
51  * @version 1, 8.4.2021
52  */
53 public class ListHandler extends AbstractHandler {
e60cff 54   
U 55   private static final Logger logger = Logger.getLogger(ListHandler.class.getName());
095119 56   
U 57   public static final String ALLE_TITEL = "alle";
f70acb 58   
U 59   private String conf;
60   
61   public ListHandler(String conf) {
62     this.conf = conf;
63   }
8d7d35 64
U 65   @Override
66   protected String get(HttpExchange e) {
e60cff 67     String path = e.getRequestURI().toString();
0e9cd3 68     String[] elems = path.split(Server.SLASH);
43d323 69     if(elems.length > 5) {
U 70       if(elems[5].endsWith("m3u")) {
71         Headers headers = e.getResponseHeaders();
72         headers.add("Content-Type", "application/m3u");
73         return getM3u(e, elems[4]);
74       } else {
a6081c 75         try {
U 76           int index = Integer.parseInt(elems[5]);
77           return getTitel(elems[4], index);
78         } catch(NumberFormatException ex) {
79           return "ungueltig";
80         }
43d323 81       }
U 82     } else {
83       String plname = elems[elems.length - 1];
84       FileStorage fs = new FileStorage(conf);
85       String json = fs.readJson(FileStorage.ST_ABSPIELLISTE, plname);
86       return embedInCustomType(json, FileStorage.ST_ABSPIELLISTE);
87     }
88   }
89   
90   private String getM3u(HttpExchange e, String plname) {
91     StringBuilder sb = new StringBuilder();
92     FileStorage fs = new FileStorage(conf);    
93     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
94     if (entity instanceof Abspielliste) {
95       Abspielliste liste = (Abspielliste) entity;
96       List<Titel> titelListe = liste.getTitel();
97       
98       for(Titel titel : titelListe) {
03b95f 99         String server = getEinstellung(fs, 
U 100                 getResString(MediaSteuerung.RB_HOST), MediaSteuerung.DEFAULT_HOST);
101         sb.append(server);
43d323 102         sb.append(titel.getKatalogUrl());
U 103         sb.append(titel.getPfad());
104         sb.append(titel.getName());
03b95f 105         sb.append(Server.NEWLINE);
43d323 106       }
U 107     }
108     return sb.toString();
8d7d35 109   }
U 110
111   @Override
112   protected String put(HttpExchange e) throws IOException {
e60cff 113     String path = e.getRequestURI().toString();
0e9cd3 114     String[] elems = path.split(Server.SLASH);
e60cff 115     String response = "ListHandler.put: ungueltiger URL";
U 116     switch(elems.length) {
8e2578 117       case 5: // ohne nr am Ende
e60cff 118         response = addTitel(e, elems[4]);
U 119         break;
120         
121       case 6:
1bf4f6 122         response = insertTitel(e, elems[4], Integer.parseInt(elems[5]));
e60cff 123         break;
1bf4f6 124         
U 125       case 7:
126         response = moveTitel(e, elems[4], Integer.parseInt(elems[5]), Integer.parseInt(elems[6]));
127         break;
128     }
129     return response;
130   }
131   
a6081c 132   private String getTitel(String plname, int index) {
U 133     FileStorage fs = new FileStorage(conf);
134     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
135     String response = "eom";
136     if(entity instanceof Abspielliste) {
137       Abspielliste aliste = (Abspielliste) entity;
138       //String titelJson = bodyLesen(e);
139       List<Titel> titelListe = aliste.getTitel();
140       if(index < titelListe.size()) {
141         Titel titel = aliste.getTitel().get(index);
142         Gson gson = new Gson();
143         response = gson.toJson(titel);
144       }
145     }
146     return response;    
147   }
148   
1bf4f6 149   /**
U 150    * Den Titel im Body von seiner aktuellen Position an die angegebene 
151    * Position setzen. Der Titel an der angegebenen Position rueckt nach 
152    * unten.
153    * 
154    * Annahme: Die Abspielliste enthaelt keine Titel mehrfach.
155    * 
156    * @param e
157    * @param plname
158    * @param zielPos
159    * @return
160    * @throws IOException 
161    */
162   private String moveTitel(HttpExchange e, String plname, int pos, int zielPos) throws IOException {
163     FileStorage fs = new FileStorage(conf);
164     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
165     String response = "Titel konnte nicht verschoben werden.";
166     if(entity instanceof Abspielliste) {
167       if(pos < zielPos) {
168         --zielPos;
169       }
170       Abspielliste aliste = (Abspielliste) entity;
171       List<Titel> liste = aliste.getTitel();
172       Titel t = liste.get(pos);
173       liste.remove(pos);
174       liste.add(zielPos, t);
175       fs.write(aliste, true);
176       response = "Titel " + t.getName() + " der Liste " + aliste.getName() + 
177               " an Position " + zielPos + " verschoben.";
178     }
179     return response;
180   }
181   
182   /**
183    * Den Titel im Body an Position anPos einfuegen. Der Titel an anPos 
184    * rueckt nach unten.
185    * 
186    * @param e
187    * @param plname
188    * @param anPos
189    * @return
190    * @throws IOException 
191    */
192   private String insertTitel(HttpExchange e, String plname, int anPos) throws IOException {
193     FileStorage fs = new FileStorage(conf);
194     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
195     String response = "Titel konnte nicht hinzugefuegt werden.";
196     if(entity instanceof Abspielliste) {
197       Abspielliste aliste = (Abspielliste) entity;
198       String titelJson = bodyLesen(e);
199       Gson gson = new Gson();
200       Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
201       if(o instanceof Titel) {
202         Titel titel = (Titel) o;
203         aliste.putTitel(titel, anPos);
204         fs.write(aliste, true);
205         response = "Titel " + titel.getName() + " der Liste " + aliste.getName() + 
206                 " an Position " + anPos + " hinzugefuegt.";
207       }
e60cff 208     }
U 209     return response;
210   }
211   
212   private String addTitel(HttpExchange e, String plname) throws IOException {
f70acb 213     FileStorage fs = new FileStorage(conf);
e60cff 214     Entity entity = fs.read(FileStorage.ST_ABSPIELLISTE, plname);
U 215     String response = "Titel konnte nicht hinzugefuegt werden.";
216     if(entity instanceof Abspielliste) {
217       Abspielliste aliste = (Abspielliste) entity;
218       String titelJson = bodyLesen(e);
219       Gson gson = new Gson();
220       Object o = gson.fromJson(titelJson, fs.typeFromName(Titel.class.getSimpleName()).getType());
221       if(o instanceof Titel) {
222         Titel titel = (Titel) o;
223         aliste.addTitel(titel);
224         fs.write(aliste, true);
225         response = "Titel " + titel.getName() + " der Liste " + aliste.getName() + " hinzugefuegt.";
226       }
227     }
228     return response;
8d7d35 229   }
U 230
172013 231   // DELETE /mz/api/alist/[pl-name]/[nr]  den Titel an der Position [nr] aus der Liste [pl-name] entfernen  
8d7d35 232   @Override
U 233   protected boolean delete(HttpExchange e) {
172013 234     String path = e.getRequestURI().toString();
U 235     String[] elems = path.split(Server.SLASH);
5f7e0b 236     String listName = elems[elems.length - 2];
f70acb 237     FileStorage fs = new FileStorage(conf);
172013 238     Entity entity = fs.read(Abspielliste.class.getSimpleName(), listName);
U 239     if(entity instanceof Abspielliste) {
240       Abspielliste liste = (Abspielliste) entity;
095119 241       String titelStr = elems[elems.length-1];
U 242       if(titelStr.equalsIgnoreCase(ALLE_TITEL)) {
243         liste.getTitel().clear();
244       } else {
245         liste.getTitel().remove(Integer.parseInt(elems[elems.length-1]));
246       }
172013 247       fs.write(liste, true);
U 248       return true;
249     } else {
250       return false;
251     }
8d7d35 252   }
U 253   
254 }