// Copyright 2009 Google Inc.
package org.npr.api;
import android.content.Context;
import android.util.Log;
import org.apache.http.client.ClientProtocolException;
import org.npr.android.util.NodeUtils;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
public abstract class StoryGrouping extends ApiElement implements
Comparable<StoryGrouping> {
private static final String LOG_TAG = StoryGrouping.class.getName();
private final String title;
private final int storycounttoday;
private final int storycountmonth;
private final int storycountall;
private final String additionalInfo;
public StoryGrouping(String id, String title, Integer storycounttoday,
Integer storycountmonth, Integer storycountall, String additionalInfo) {
super(id);
this.title = title;
this.storycounttoday = storycounttoday;
this.storycountmonth = storycountmonth;
this.storycountall = storycountall;
this.additionalInfo = additionalInfo;
}
public String getTitle() {
return title;
}
public String getAdditionalInfo() {
return additionalInfo;
}
@Override
public String toString() {
return title;
}
@Override
public int compareTo(StoryGrouping that) {
int today, month, all;
today = this.storycounttoday - that.storycounttoday;
month = this.storycountmonth - that.storycountmonth;
all = this.storycountall - that.storycountall;
boolean equal = today == 0 && month == 0 && all == 0;
if (today > 0) {
return -1;
} else {
if (month > 0) {
return -1;
} else {
if (all > 0) {
return -1;
}
}
}
return equal ? 0 : 1;
}
public static class StoryGroupingBuilder<T extends StoryGrouping> {
protected final Class<T> klass;
protected final String id;
protected String title;
protected final int storycounttoday;
protected final int storycountmonth;
protected final int storycountall;
protected String additionalInfo;
public StoryGroupingBuilder(Class<T> c, String id, int storycounttoday,
int storycountmonth, int storycountall) {
this.klass = c;
this.id = id;
this.storycounttoday = storycounttoday;
this.storycountmonth = storycountmonth;
this.storycountall = storycountall;
}
public StoryGroupingBuilder<T> withTitle(String title) {
this.title = title;
return this;
}
public StoryGroupingBuilder<T> withAdditionalInfo(String additionalInfo) {
this.additionalInfo = additionalInfo;
return this;
}
public T build() {
try {
Constructor<T> cons =
klass.getConstructor(String.class, String.class, int.class,
int.class, int.class, String.class);
return cons.newInstance(id, title, storycounttoday, storycountmonth,
storycountall, additionalInfo);
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
return null;
}
}
public static class StoryGroupingFactory<T extends StoryGrouping> {
public StoryGroupingFactory(Class<T> klass, String groupingType) {
this.klass = klass;
this.groupingType = groupingType;
}
private final Class<T> klass;
private final String groupingType;
protected List<T> parseStoryGroupings(Class<T> c, Node rootNode) {
LinkedList<T> result = new LinkedList<T>();
TreeSet<T> resultSet = new TreeSet<T>();
NodeList childNodes = rootNode.getChildNodes();
for (Node node : new IterableNodeList(childNodes)) {
T p = createStoryGrouping(c, node);
if (p != null) {
resultSet.add(p);
}
}
for (T p : resultSet) {
result.add(p);
}
return result;
}
@SuppressWarnings("unchecked")
protected T createStoryGrouping(Class<T> c, Node node) {
if (!node.getNodeName().equals("item") ||
!node.hasChildNodes()) {
return null;
}
String id;
int storycounttoday, storycountmonth, storycountall;
id = node.getAttributes().getNamedItem("id").getNodeValue();
storycountall = Integer.parseInt(node.getAttributes().getNamedItem(
"storycountall").getNodeValue());
storycountmonth = Integer.parseInt(node.getAttributes().getNamedItem(
"storycountmonth").getNodeValue());
storycounttoday = Integer.parseInt(node.getAttributes().getNamedItem(
"storycounttoday").getNodeValue());
StoryGroupingBuilder<? extends StoryGrouping> sb =
new StoryGroupingBuilder<T>(c, id, storycounttoday, storycountmonth,
storycountall);
for (Node n : new IterableNodeList(node.getChildNodes())) {
String nodeName = n.getNodeName();
if (nodeName.equals("title")) {
sb.withTitle(NodeUtils.getTextContent(n));
} else if (nodeName.equals("additionalInfo")) {
sb.withAdditionalInfo(NodeUtils.getTextContent(n));
}
}
return (T) sb.build();
}
public List<T> downloadStoryGroupings(int count, Context context) {
Log.d(LOG_TAG, "downloading StoryGroupings");
Map<String, String> params = new HashMap<String, String>();
params.put(ApiConstants.PARAM_ID, groupingType);
String url = ApiConstants.instance()
.createUrl(ApiConstants.LIST_PATH, params);
Node storyGroupings = null;
try {
storyGroupings = new Client(url, context).execute();
} catch (ClientProtocolException e) {
Log.e(LOG_TAG, "", e);
} catch (IOException e) {
Log.e(LOG_TAG, "", e);
} catch (SAXException e) {
Log.e(LOG_TAG, "", e);
} catch (ParserConfigurationException e) {
Log.e(LOG_TAG, "", e);
}
if (storyGroupings == null) {
return new LinkedList<T>();
}
Log.d(LOG_TAG, "node " + storyGroupings.getNodeName() + " "
+ storyGroupings.getChildNodes().getLength());
List<T> result = parseStoryGroupings(klass, storyGroupings);
Log.d(LOG_TAG, "found StoryGroupings: " + result.size());
return (count >= 0 && count < result.size()) ?
result.subList(0, count) :
result;
}
}
}