From a33024c4fdfb76002e3cb66486906aaa047dd230 Mon Sep 17 00:00:00 2001 From: veronie Date: Sun, 1 Mar 2020 01:00:53 +0100 Subject: [PATCH] Added BggApi class that downloads and parses XML results. User collection results are shown in result table. Basic infrastructure for geeklist id and family id (TODO). --- .../src/xyz/veronie/bgg/result/BggApi.java | 224 ++++++++++++++++++ .../src/xyz/veronie/bgg/result/BggFamily.java | 5 + .../xyz/veronie/bgg/result/ResultConfig.java | 10 +- .../bgg/result/ResultConfigManager.java | 26 +- .../xyz/veronie/bgg/result/ThingMetaData.java | 104 +++++--- .../xyz/veronie/bgg/result/ThingProvider.java | 15 +- .../src/xyz/veronie/bgg/types/BggResult.java | 6 - .../xyz/veronie/bgg/types/EventConstants.java | 7 +- .../src/xyz/veronie/bgg/types/Subtype.java | 5 +- .../xyz/veronie/bgg/types/SubtypeEvent.java | 6 - .../src/xyz/veronie/bgg/types/UserFlag.java | 37 ++- .../bgg/ui/filters/BggUserSourceFilter.java | 9 +- .../bgg/ui/filters/FamilySourceFilter.java | 46 +++- .../bgg/ui/filters/GeeklistSourceFilter.java | 22 +- .../veronie/bgg/ui/filters/SubtypeGroup.java | 54 ----- .../veronie/bgg/ui/parts/BggResultPart.java | 102 +++----- .../veronie/bgg/ui/parts/LoadFromBggPart.java | 82 +++++-- 17 files changed, 513 insertions(+), 247 deletions(-) create mode 100644 xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggApi.java create mode 100644 xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggFamily.java delete mode 100644 xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/BggResult.java delete mode 100644 xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/SubtypeEvent.java delete mode 100644 xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/SubtypeGroup.java diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggApi.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggApi.java new file mode 100644 index 0000000..06edaf5 --- /dev/null +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggApi.java @@ -0,0 +1,224 @@ +package xyz.veronie.bgg.result; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map.Entry; + +import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.e4.core.di.annotations.Creatable; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import xyz.veronie.bgg.types.FilterFlagState; +import xyz.veronie.bgg.types.Subtype; +import xyz.veronie.bgg.types.UserFlag; + +@Creatable +public class BggApi { + + @Inject private ResultConfigManager configManager; + + public static String BASE_URL = "https://www.boardgamegeek.com/xmlapi2/"; + public static String USER = "user"; + public static String COLLECTION = "collection"; + public static String SEARCH = "search"; + public static String FAMILY = "family"; + public static String GEEKLIST = "geeklist"; + + private static int RETRIES = 5; + + public ArrayList getThingsForUser(String user) { + ResultConfig resultConfig = configManager.getResultConfig(); + + StringBuilder urlStr = new StringBuilder(); + urlStr.append(BASE_URL + COLLECTION + + "?username=" + resultConfig.user + + "&subtype=" + resultConfig.subtype.toApiString() + "&"); + if(resultConfig.subtype == Subtype.BOARDGAME) { + urlStr.append("excludesubtype=" + Subtype.BGEXPANSION.toApiString() + "&"); + } + + Iterator> ufIterator + = resultConfig.userFlags.entrySet().iterator(); + + try { + while(ufIterator.hasNext()) { + Entry elem = ufIterator.next(); + String apiString = elem.getKey().toApiString(); + FilterFlagState state = elem.getValue(); + if(state == FilterFlagState.IS) { + urlStr.append(URLEncoder.encode(apiString, "UTF-8")); + urlStr.append("=1&"); + } else if (state == FilterFlagState.ISNOT) { + urlStr.append(URLEncoder.encode(apiString, "UTF-8")); + urlStr.append("=0&"); + } + } + } + catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + + return getThings(urlStr.toString()); + } + + + public ArrayList getThingsForGeeklist(int geeklistId) { + ResultConfig resultConfig = configManager.getResultConfig(); + + StringBuilder urlStr = new StringBuilder(); + urlStr.append(BASE_URL + GEEKLIST + "/" + String.valueOf(resultConfig.geeklistId)); + + return getThings(urlStr.toString()); + } + + + + private ArrayList getThings(String urlString) { + System.out.println("URL: " + urlString); + + try { + int retry = 0; + do { + // send a GET request and check for ok... + URL url = new URL(urlString); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + int status = con.getResponseCode(); + if(status == HttpURLConnection.HTTP_ACCEPTED) { + Thread.sleep(2000); + System.out.println("Waiting for server to prepare result..."); + } + else if(status != HttpURLConnection.HTTP_OK) { + System.out.println("Http Response: " + status); + con.disconnect(); + return null; + } else { + // HTTP_OK, go on... + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer content = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + con.disconnect(); + + // do something with the content + System.out.println(content.toString()); + ArrayList output = parseThingMetas(content.toString()); + return output; + } + + ++retry; + } while (retry < RETRIES); + + } + catch (MalformedURLException e) { + System.out.println("[ERROR] Malformed URL: " + urlString); + e.printStackTrace(); + } catch (IOException e) { + System.out.println("[ERROR] Could not open connection for URL: " + urlString); + e.printStackTrace(); + } catch (InterruptedException e) { + // this will not happen, but we have to catch it anyways... + e.printStackTrace(); + } + + return null; + } + + + + private ArrayList parseThingMetas(String content) { + ArrayList metas = new ArrayList(); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + + DocumentBuilder builder = factory.newDocumentBuilder(); + InputSource is = new InputSource(new StringReader(content)); + is.setEncoding("UTF-8"); + Document doc = builder.parse(is); + Element root = doc.getDocumentElement(); + + // BGG XMLAPI2 + if(root.getTagName() == "items") { + NodeList nList = doc.getElementsByTagName("item"); + for(int i = 0; i < nList.getLength(); i++) { + Node nNode = nList.item(i); + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + Element eElement = (Element) nNode; + ThingMetaData tmd = new ThingMetaData( + Integer.parseInt(eElement.getAttribute("objectid")), + getValue(eElement, "name"), + getValue(eElement, "image"), + getValue(eElement, "thumbnail"), + getValue(eElement, "comment"), + Integer.parseInt(getValue(eElement, "numplays")) + ); + metas.add(tmd); + } + } + } + // for geeklist result (XMLAPI) + else if(root.getTagName() == "geeklist") { + NodeList nList = doc.getElementsByTagName("item"); + for(int i = 0; i < nList.getLength(); i++) { + Node nNode = nList.item(i); + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + Element eElement = (Element) nNode; + ThingMetaData tmd = new ThingMetaData( + Integer.parseInt(eElement.getAttribute("objectid")), + eElement.getAttribute("objectname"), + "", "", "", null); + metas.add(tmd); + } + } + } + + return metas; + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + + + return null; + } + + private String getValue(Element eElement, String key) { + Node node = eElement.getElementsByTagName(key).item(0); + if(node == null) { + return ""; + } else { + return node.getTextContent(); + } + } + + +} diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggFamily.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggFamily.java new file mode 100644 index 0000000..abda4f5 --- /dev/null +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/BggFamily.java @@ -0,0 +1,5 @@ +package xyz.veronie.bgg.result; + +public class BggFamily { + +} diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfig.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfig.java index 3c69a8c..e4da60c 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfig.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfig.java @@ -15,15 +15,7 @@ public class ResultConfig { public SourceFilter source = SourceFilter.BGG_USER; public ResultAction action = ResultAction.ADD; - public HashMap subTypes = new HashMap() { - private static final long serialVersionUID = -8718858283141976457L; - - { - for (Subtype st : Subtype.values()) { - put(st, false); - } - put(Subtype.BOARDGAME, true); - }}; + public Subtype subtype = Subtype.BOARDGAME; // bgg user filter settings public String user = ""; diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfigManager.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfigManager.java index 03c0341..b096bc2 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfigManager.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ResultConfigManager.java @@ -11,7 +11,7 @@ import org.eclipse.e4.ui.di.UIEventTopic; import xyz.veronie.bgg.types.EventConstants; import xyz.veronie.bgg.types.ResultAction; import xyz.veronie.bgg.types.SourceFilter; -import xyz.veronie.bgg.types.SubtypeEvent; +import xyz.veronie.bgg.types.Subtype; import xyz.veronie.bgg.types.UserFlagEvent; @@ -43,9 +43,9 @@ public class ResultConfigManager { @Optional private void subscribeTopicSubtypesChanged (@UIEventTopic(EventConstants.TOPIC_SUBTYPE_CHANGED) - SubtypeEvent se) { - getResultConfig().subTypes.put(se.subtype, se.checked); - System.out.println("TOPIC_SUBTYPE_CHANGED: " + (se.checked?"[x] ":"[ ] ") + se.subtype); + Subtype subtype) { + getResultConfig().subtype = subtype; + System.out.println("TOPIC_SUBTYPE_CHANGED: " + subtype); } @Inject @@ -75,7 +75,25 @@ public class ResultConfigManager { getResultConfig().action = action; System.out.println("TOPIC_ACTION_CHANGED: action = " + action); } + + @Inject + @Optional + private void subscribeTopicResultGeeklistChanged + (@UIEventTopic(EventConstants.TOPIC_GEEKLIST_CHANGED) + Integer id) { + getResultConfig().geeklistId = id; + System.out.println("TOPIC_GEEKLIST_CHANGED: geeklistId = " + id); + } + @Inject + @Optional + private void subscribeTopicResultFamilyChanged + (@UIEventTopic(EventConstants.TOPIC_FAMILY_CHANGED) + Integer id) { + getResultConfig().familyId = id; + System.out.println("TOPIC_FAMILY_CHANGED: geeklistId = " + id); + } + public ResultConfig getResultConfig() { return resultConfig; } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingMetaData.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingMetaData.java index 4f644a2..a642583 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingMetaData.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingMetaData.java @@ -3,25 +3,32 @@ package xyz.veronie.bgg.result; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; + public class ThingMetaData { private int id; - private Integer rating; + private String name; private String imgURL; private String thumbURL; private String comment; - private Integer otherId; // ??? - private String username; + private Integer numPlays; + private static String[] titles = { "Id", "Name", "Image", "Thumb", "comment", "# plays"}; + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - public ThingMetaData(int id, Integer rating, String imgURL, String thumbURL, String comment, Integer otherId, String username) { + public ThingMetaData(int id, String name, + String imgURL, String thumURL, + String comment, Integer numPlays) { this.setId(id); - this.setRating(rating); + this.setName(name); this.setImgURL(imgURL); - this.setThumbURL(thumbURL); + this.setThumbURL(thumURL); this.setComment(comment); - this.setOtherId(otherId); - this.setUsername(username); + this.setNumPlays(numPlays); + } + + public static String[] getTitles() { + return titles; } public void addPropertyChangeListener(String propertyName, @@ -32,6 +39,42 @@ public class ThingMetaData { public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(listener); } + + /// get field at idx, order of titles + public String getField(int idx) { + if(idx >= titles.length) { + + } + + String returnStr; + + switch(idx) { + case 0: + returnStr = String.valueOf(this.id); + break; + case 1: + returnStr = this.name; + break; + case 2: + returnStr = this.imgURL; + break; + case 3: + returnStr = this.thumbURL; + break; + case 4: + returnStr = this.comment; + break; + case 5: + returnStr = String.valueOf(this.numPlays); + break; + default: + throw new ArrayIndexOutOfBoundsException( + "idx " + String.valueOf(idx) + " must be in [0," + (titles.length-1) + "]"); + } + + return returnStr; + } + public int getId() { return id; @@ -42,15 +85,16 @@ public class ThingMetaData { this.id = id); } - public Integer getRating() { - return rating; + + public String getName() { + return name; } - public void setRating(Integer rating) { - propertyChangeSupport.firePropertyChange("rating", this.rating, - this.rating = rating); + public void setName(String name) { + propertyChangeSupport.firePropertyChange("name", this.name, + this.name = name); } - + public String getImgURL() { return imgURL; } @@ -63,44 +107,34 @@ public class ThingMetaData { public String getThumbURL() { return thumbURL; } - + public void setThumbURL(String thumbURL) { propertyChangeSupport.firePropertyChange("thumb", this.thumbURL, this.thumbURL = thumbURL); } - public String getComment() { - return comment; + public int getNumPlays() { + return numPlays; } - public void setComment(String comment) { - propertyChangeSupport.firePropertyChange("comment", this.comment, - this.comment = comment); + public void setNumPlays(Integer numPlays) { + this.numPlays = numPlays; } - public Integer getOtherId() { - return otherId; - } - public void setOtherId(Integer otherId) { - propertyChangeSupport.firePropertyChange("otherId", this.otherId, - this.otherId = otherId); + public String getComment() { + return comment; } - public String getUsername() { - return username; + public void setComment(String comment) { + propertyChangeSupport.firePropertyChange("comment", this.comment, + this.comment = comment); } - public void setUsername(String username) { - propertyChangeSupport.firePropertyChange("username", this.username, - this.username = username); - } - - @Override public String toString() { return String.valueOf(id); } - + } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingProvider.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingProvider.java index cd8d61e..8200a25 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingProvider.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/result/ThingProvider.java @@ -10,17 +10,10 @@ public enum ThingProvider { private ThingProvider() { thingMetas = new ArrayList(); - - // TODO: retrieve data from BGG - // ...and iterate: - thingMetas.add(new ThingMetaData( - 286053, - null, - "https://cf.geekdo-images.com/original/img/vKBCxo7d6maBDC_X9nmC5MWzIC8=/0x0/pic4880614.jpg", - "https://cf.geekdo-images.com/thumb/img/gpeB-GrXrknzAqFKEky1JOvcY4w=/fit-in/200x150/pic4880614.jpg", - "", - 65212097, - "veronie")); + } + + public void setThingMetas(ArrayList metas) { + this.thingMetas = metas; } public List getThingMetas() { diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/BggResult.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/BggResult.java deleted file mode 100644 index 7eb2f5b..0000000 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/BggResult.java +++ /dev/null @@ -1,6 +0,0 @@ -package xyz.veronie.bgg.types; - -/// This class contains and handles the result table for BGG things -public class BggResult { - -} diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/EventConstants.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/EventConstants.java index ba5fe10..97c6f2e 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/EventConstants.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/EventConstants.java @@ -2,7 +2,7 @@ package xyz.veronie.bgg.types; public interface EventConstants { - String TOPIC_CONFIG_CHANGED = "CONFIG_CHANGED/*"; + String TOPIC_CONFIG_CHANGED = "CONFIG_CHANGED"; String TOPIC_SOURCE_CHANGED = "CONFIG_CHANGED/FILTER"; @@ -16,4 +16,9 @@ public interface EventConstants { String TOPIC_GEEKLIST_CHANGED = "CONFIG_CHANGED/GEEKLIST"; + String TOPIC_FAMILY_CHANGED = "CONFIG_CHANGED/FAMILY"; + + String TOPIC_RESULT_CHANGED = "RESULT_CHANGED"; + + } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/Subtype.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/Subtype.java index f2ec9d7..1681951 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/Subtype.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/Subtype.java @@ -20,9 +20,10 @@ public enum Subtype { public String toString() { return this.name; } - + /// return the string used in BGG XMLAPI2 to identify the thingtype - public String toSubtypeString() { + public String toApiString() { return this.thingTypeString; } + } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/SubtypeEvent.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/SubtypeEvent.java deleted file mode 100644 index b8a27f3..0000000 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/SubtypeEvent.java +++ /dev/null @@ -1,6 +0,0 @@ -package xyz.veronie.bgg.types; - -public class SubtypeEvent { - public Subtype subtype; - public Boolean checked; -} diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/UserFlag.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/UserFlag.java index dfdc0cc..c744d47 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/UserFlag.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/types/UserFlag.java @@ -2,23 +2,42 @@ package xyz.veronie.bgg.types; public enum UserFlag { - OWN("owned"), - PREVIOUSLY_OWNED("previously owned"), - FOR_TRADE("for trade"), - WANTED("wanted"), - WTP("want to play"), - WTB("want to buy"), - WISHLIST("on wishlist"), - PREORDERED("preordered"); + OWN("owned", "own"), + PREVIOUSLY_OWNED("previously owned", "prevowned"), + TRADE("for trade", "trade"), + WANT("wanted", "want"), + WTP("want to play", "wanttoplay"), + WTB("want to buy", "wanttobuy"), + WISHLIST("on wishlist", "wishlist"), + PREORDERED("pre-ordered", "preordered"), + + RATED("rated", "rated"), + PLAYED("played", "played"), + COMMENT("commented", "comment"); + +// MINRATING("min rating", "minrating"), +// MAXRATING("max rating", "rating"), +// MIN_BGG_RATING("min BGG rating", "minbggrating"), +// MAX_BGG_RATING("max BGG rating", "bggrating"), +// MIN_PLAYS("min plays", "minplays"), +// MAX_PLAYS("max plays, "maxplays"), +// MODIFIED_SINCE("modified since", "modifiedsince"); + private String flag; + private String apiString; - private UserFlag(String flag) { + private UserFlag(String flag, String apiString) { this.flag = flag; + this.apiString = apiString; } @Override public String toString() { return this.flag; } + + public String toApiString() { + return this.apiString; + } } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/BggUserSourceFilter.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/BggUserSourceFilter.java index e4aee1b..be5b65b 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/BggUserSourceFilter.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/BggUserSourceFilter.java @@ -106,12 +106,17 @@ public class BggUserSourceFilter { makeFilter(parent, UserFlag.PREVIOUSLY_OWNED); makeFilter(parent, UserFlag.WTB); - makeFilter(parent, UserFlag.FOR_TRADE); + makeFilter(parent, UserFlag.TRADE); makeFilter(parent, UserFlag.WISHLIST); - makeFilter(parent, UserFlag.WANTED); + makeFilter(parent, UserFlag.WANT); makeFilter(parent, UserFlag.PREORDERED); + makeFilter(parent, UserFlag.RATED); + makeFilter(parent, UserFlag.COMMENT); + + makeFilter(parent, UserFlag.PLAYED); + parent.layout(); } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/FamilySourceFilter.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/FamilySourceFilter.java index cf46f08..ad19b06 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/FamilySourceFilter.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/FamilySourceFilter.java @@ -1,5 +1,10 @@ package xyz.veronie.bgg.ui.filters; +import javax.inject.Inject; + +import org.eclipse.e4.core.di.annotations.Creatable; +import org.eclipse.e4.core.services.events.IEventBroker; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; @@ -11,11 +16,17 @@ import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; +import xyz.veronie.bgg.result.ResultConfigManager; +import xyz.veronie.bgg.types.EventConstants; + /// These are the controls to retrieve thing IDs for a given family ID +@Creatable public class FamilySourceFilter { - private static int familyId; - public static void create(Composite parent, int style) { + @Inject private IEventBroker eventBroker; + @Inject private ResultConfigManager configManager; + + public void create(Composite parent, int style) { GridLayout filterLayout = new GridLayout(2, false); parent.setLayout(filterLayout); @@ -27,16 +38,28 @@ public class FamilySourceFilter { cbFamilyId.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); cbFamilyId.addSelectionListener(new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e) { - setFamilyId(Integer.getInteger(cbFamilyId.getText())); - System.out.println("set geeklist id to '" + getFamilyId() + "'"); + try { + setFamilyId(Integer.parseInt(cbFamilyId.getText())); + System.out.println("set family id to '" + configManager.getResultConfig().geeklistId + "'"); + } + catch (NumberFormatException ex) { + MessageDialog.openError(parent.getShell(), "Input error", "FamilyId must be a whole number."); + } + System.out.println("set family id to '" + configManager.getResultConfig().familyId + "'"); } }); cbFamilyId.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { - setFamilyId(Integer.getInteger(cbFamilyId.getText())); - System.out.println("set geeklist id to '" + getFamilyId() + "'"); + try { + setFamilyId(Integer.parseInt(cbFamilyId.getText())); + System.out.println("set family id to '" + configManager.getResultConfig().geeklistId + "'"); + } + catch (NumberFormatException ex) { + MessageDialog.openError(parent.getShell(), "Input error", "FamilyId must be a whole number."); + } + System.out.println("set family id to '" + configManager.getResultConfig().familyId + "'"); } @Override @@ -47,11 +70,12 @@ public class FamilySourceFilter { parent.layout(); } - public static int getFamilyId() { - return familyId; - } - public static void setFamilyId(int familyId) { - FamilySourceFilter.familyId = familyId; + public void setFamilyId(int familyId) { + if(eventBroker != null) { + eventBroker.post(EventConstants.TOPIC_FAMILY_CHANGED, familyId); + } else { + System.out.println("setFamilyId: eventBroker is null."); + } } } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/GeeklistSourceFilter.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/GeeklistSourceFilter.java index 0d8343f..5735f5b 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/GeeklistSourceFilter.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/GeeklistSourceFilter.java @@ -4,6 +4,7 @@ import javax.inject.Inject; import org.eclipse.e4.core.di.annotations.Creatable; import org.eclipse.e4.core.services.events.IEventBroker; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; @@ -23,7 +24,7 @@ import xyz.veronie.bgg.types.EventConstants; public class GeeklistSourceFilter { @Inject private IEventBroker eventBroker; - @Inject ResultConfigManager configManager; + @Inject private ResultConfigManager configManager; public void create(Composite parent, int style) { GridLayout filterLayout = new GridLayout(2, false); @@ -37,16 +38,27 @@ public class GeeklistSourceFilter { cbGeeklistId.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); cbGeeklistId.addSelectionListener(new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e) { - setGeeklistId(Integer.getInteger(cbGeeklistId.getText())); - System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); + try { + setGeeklistId(Integer.parseInt(cbGeeklistId.getText())); + System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); + } + catch (NumberFormatException ex) { + MessageDialog.openError(parent.getShell(), "Input error", "GeeklistId must be a whole number."); + } } }); cbGeeklistId.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { - setGeeklistId(Integer.getInteger(cbGeeklistId.getText())); - System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); + try { + setGeeklistId(Integer.parseInt(cbGeeklistId.getText())); + System.out.println("set geeklist id to '" + configManager.getResultConfig().geeklistId + "'"); + } + catch (NumberFormatException ex) { + MessageDialog.openError(parent.getShell(), "Input error", "GeeklistId must be a whole number."); + } + } @Override diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/SubtypeGroup.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/SubtypeGroup.java deleted file mode 100644 index b79db30..0000000 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/filters/SubtypeGroup.java +++ /dev/null @@ -1,54 +0,0 @@ -package xyz.veronie.bgg.ui.filters; - -import java.util.HashMap; - -import org.eclipse.e4.core.services.events.IEventBroker; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; - -import xyz.veronie.bgg.result.ResultConfigManager; -import xyz.veronie.bgg.types.EventConstants; -import xyz.veronie.bgg.types.Subtype; -import xyz.veronie.bgg.types.SubtypeEvent; - -public class SubtypeGroup { - private HashMap buttons; - - public void create(Composite parent, IEventBroker eventBroker, ResultConfigManager configManager) { - Group gSubtype = new Group(parent, SWT.LEFT); - gSubtype.setText("Subtypes"); - gSubtype.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - gSubtype.setLayout(new GridLayout(1, false)); - - buttons = new HashMap(); - - for (Subtype st : Subtype.values()) { - Button bb = new Button(gSubtype, SWT.CHECK); - bb.setText(st.toString()); - bb.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - - // init - HashMap configuredTypes = configManager.getResultConfig().subTypes; - bb.setSelection(configuredTypes.get(st)); - bb.addSelectionListener(new SelectionAdapter() - { - @Override - public void widgetSelected(SelectionEvent e) - { - SubtypeEvent stEvent = new SubtypeEvent(); - stEvent.subtype = st; - stEvent.checked = bb.getSelection(); - eventBroker.send(EventConstants.TOPIC_SUBTYPE_CHANGED, stEvent); - } - }); - buttons.put(st, bb); - } - } - -} diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/BggResultPart.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/BggResultPart.java index ee4725c..613df2e 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/BggResultPart.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/BggResultPart.java @@ -1,7 +1,10 @@ package xyz.veronie.bgg.ui.parts; import javax.annotation.PostConstruct; +import javax.inject.Inject; +import org.eclipse.e4.core.di.annotations.Optional; +import org.eclipse.e4.ui.di.UIEventTopic; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.TableViewer; @@ -15,10 +18,11 @@ import org.eclipse.swt.widgets.TableColumn; import xyz.veronie.bgg.result.ThingMetaData; import xyz.veronie.bgg.result.ThingProvider; +import xyz.veronie.bgg.types.EventConstants; public class BggResultPart { private TableViewer viewer; - + @PostConstruct public void createControls(Composite parent) { Composite main = new Composite(parent, SWT.FILL); @@ -61,79 +65,19 @@ public class BggResultPart { // This will create the columns for the table private void createColumns(final Composite parent, final TableViewer viewer) { - String[] titles = { "Id", "Rating", "Image", "Thumb", "comment", "other Id", "User name" }; - int[] bounds = { 100, 100, 100, 100, 100, 100, 100 }; - - // First column id - TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return String.valueOf(t.getId()); - } - }); - - // Second column rating - col = createTableViewerColumn(titles[1], bounds[1], 1); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return String.valueOf(t.getRating()); - } - }); - - // now img url - col = createTableViewerColumn(titles[2], bounds[2], 2); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return t.getImgURL(); - } - }); - - // thumb url - col = createTableViewerColumn(titles[3], bounds[3], 3); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return t.getThumbURL(); - } - }); + String[] titles = ThingMetaData.getTitles(); + int[] bounds = { 100, 100, 100, 100, 100, 100 }; - // comment - col = createTableViewerColumn(titles[4], bounds[4], 4); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return t.getComment(); - } - }); - - // other id - col = createTableViewerColumn(titles[5], bounds[5], 5); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return String.valueOf(t.getOtherId()); - } - }); - - // username - col = createTableViewerColumn(titles[6], bounds[6], 6); - col.setLabelProvider(new ColumnLabelProvider() { - @Override - public String getText(Object element) { - ThingMetaData t = (ThingMetaData) element; - return String.valueOf(t.getUsername()); - } - }); - + for(int i = 0; i < titles.length; ++i) { + TableViewerColumn col = createTableViewerColumn(titles[i], bounds[i], i); + col.setLabelProvider(new ColumnLabelProvider() { + @Override + public String getText(Object element) { + ThingMetaData t = (ThingMetaData) element; + return t.getField((int)col.getColumn().getData()); + } + }); + } } private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) { @@ -144,6 +88,7 @@ public class BggResultPart { column.setWidth(bound); column.setResizable(true); column.setMoveable(true); + column.setData(colNumber); return viewerColumn; } @@ -154,5 +99,16 @@ public class BggResultPart { public void setFocus() { viewer.getControl().setFocus(); } + + + @Inject + @Optional + private void subscribeTopicResultChanged + (@UIEventTopic(EventConstants.TOPIC_RESULT_CHANGED) + String empty) { + System.out.println("TOPIC_RESULT_CHANGED"); + viewer.setInput(ThingProvider.INSTANCE.getThingMetas()); + viewer.refresh(); + } } diff --git a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/LoadFromBggPart.java b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/LoadFromBggPart.java index 5c7e0e2..dec5514 100644 --- a/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/LoadFromBggPart.java +++ b/xyz.veronie.bgg.ui/src/xyz/veronie/bgg/ui/parts/LoadFromBggPart.java @@ -1,6 +1,6 @@ package xyz.veronie.bgg.ui.parts; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; @@ -26,17 +26,21 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import xyz.veronie.bgg.result.BggApi; +import xyz.veronie.bgg.result.ResultConfig; import xyz.veronie.bgg.result.ResultConfigManager; +import xyz.veronie.bgg.result.ThingMetaData; +import xyz.veronie.bgg.result.ThingProvider; import xyz.veronie.bgg.types.EventConstants; import xyz.veronie.bgg.types.ResultAction; import xyz.veronie.bgg.types.SourceFilter; +import xyz.veronie.bgg.types.Subtype; import xyz.veronie.bgg.ui.filters.AgeSourceFilter; import xyz.veronie.bgg.ui.filters.BggUserSourceFilter; import xyz.veronie.bgg.ui.filters.FamilySourceFilter; import xyz.veronie.bgg.ui.filters.GeeklistSourceFilter; import xyz.veronie.bgg.ui.filters.RankSourceFilter; import xyz.veronie.bgg.ui.filters.SearchSourceFilter; -import xyz.veronie.bgg.ui.filters.SubtypeGroup; import xyz.veronie.bgg.ui.filters.YearSourceFilter; @@ -53,6 +57,8 @@ public class LoadFromBggPart { // inject all source filter composites @Inject private BggUserSourceFilter bggUserSourceFilter; @Inject private GeeklistSourceFilter geeklistSourceFilter; + @Inject private FamilySourceFilter familySourceFilter; + @Inject private BggApi bggApi; @PostConstruct public void createControls(Composite parent) { @@ -80,9 +86,10 @@ public class LoadFromBggPart { ComboViewer cbSource = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); cbSource.setContentProvider(ArrayContentProvider.getInstance()); - List sources = Arrays.asList(new SourceFilter[] { - SourceFilter.BGG_USER, SourceFilter.GEEKLIST, SourceFilter.FAMILY, - SourceFilter.RANK, SourceFilter.YEAR, SourceFilter.AGE, SourceFilter.SEARCH }); + List sources = new ArrayList(); + for(SourceFilter sf : SourceFilter.values()) { + sources.add(sf); + } cbSource.setInput(sources); // TODO: implement all the sources @@ -90,14 +97,27 @@ public class LoadFromBggPart { // listener is configured further below - // choose the bgg sub-site + // choose the thing sub-type Label lblSubtype = new Label(dlConfigGroup, SWT.LEFT); lblSubtype.setText("Subtypes: "); lblSubtype.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false)); - SubtypeGroup gSubtypes = new SubtypeGroup(); - gSubtypes.create(dlConfigGroup, eventBroker, configManager); - + ComboViewer cbSubtypes = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); + cbSubtypes.setContentProvider(ArrayContentProvider.getInstance()); + List subtypes = new ArrayList(); + for (Subtype st : Subtype.values()) { + subtypes.add(st); + } + cbSubtypes.setInput(subtypes); + cbSubtypes.setSelection(new StructuredSelection(configManager.getResultConfig().subtype)); + cbSubtypes.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + eventBroker.send(EventConstants.TOPIC_SUBTYPE_CHANGED, selection.getFirstElement()); + } + }); + // choose action on result list Label lblAct = new Label(dlConfigGroup, SWT.LEFT); lblAct.setText("Action on result: "); @@ -105,13 +125,13 @@ public class LoadFromBggPart { ComboViewer cbAct = new ComboViewer(dlConfigGroup, SWT.READ_ONLY); cbAct.setContentProvider(ArrayContentProvider.getInstance()); - List actions = Arrays.asList(new ResultAction[] { - ResultAction.ADD, ResultAction.REP, ResultAction.SUB, - ResultAction.AND, ResultAction.MIS }); + List actions = new ArrayList(); + for(ResultAction act : ResultAction.values()) { + actions.add(act); + } cbAct.setInput(actions); cbAct.setSelection(new StructuredSelection(configManager.getResultConfig().action)); cbAct.addSelectionChangedListener(new ISelectionChangedListener() { - @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); @@ -156,21 +176,45 @@ public class LoadFromBggPart { @Override public void widgetSelected(SelectionEvent e) { System.out.println("Downloading " + cbSource.getSelection().toString()); - + ResultConfig resultConfig = configManager.getResultConfig(); + IStructuredSelection selection = (IStructuredSelection) cbSource.getSelection(); if(selection.size() == 0) return; if(selection.getFirstElement() == SourceFilter.BGG_USER) { - String user = configManager.getResultConfig().user; + String user = resultConfig.user; if(user == null || user.isEmpty()) { System.out.println("Please enter a user name."); return; + } else { + System.out.println("...for user '" + user + "'"); + ArrayList thingMetas = bggApi.getThingsForUser(user); + ThingProvider.INSTANCE.setThingMetas(thingMetas); + eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); } - System.out.println("...for user '" + user + "'"); + } else if(selection.getFirstElement() == SourceFilter.GEEKLIST) { - System.out.println("...for geeklist id '" + configManager.getResultConfig().geeklistId + "'"); + Integer geeklistId = resultConfig.geeklistId; + if(geeklistId == null) { + System.out.println("Please enter a geeklist id."); + return; + } else { + System.out.println("...for geeklist id '" + geeklistId + "'"); + ArrayList thingMetas = bggApi.getThingsForGeeklist(geeklistId); + ThingProvider.INSTANCE.setThingMetas(thingMetas); + eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); + } } else if(selection.getFirstElement() == SourceFilter.FAMILY) { - System.out.println("...for family id '" + FamilySourceFilter.getFamilyId() + "'"); + Integer familyId = resultConfig.familyId; + if(familyId == null) { + System.out.println("Please enter a family id."); + return; + } else { + System.out.println("...for family id '" + familyId + "'"); + //ArrayList thingMetas = bggApi.getThingsForFamily(familyId); + //ThingProvider.INSTANCE.setThingMetas(thingMetas); + //eventBroker.send(EventConstants.TOPIC_RESULT_CHANGED, ""); + } } } }); @@ -202,7 +246,7 @@ public class LoadFromBggPart { break; case FAMILY: System.out.println("construct " + elem); - FamilySourceFilter.create(parent, SWT.FILL); + familySourceFilter.create(parent, SWT.FILL); break; case RANK: RankSourceFilter.create(parent, SWT.FILL);