Skip to content

Instantly share code, notes, and snippets.

@john-h-kastner
Created June 17, 2015 19:27
Show Gist options
  • Save john-h-kastner/ecaeeb4ee6ab06f675aa to your computer and use it in GitHub Desktop.
Save john-h-kastner/ecaeeb4ee6ab06f675aa to your computer and use it in GitHub Desktop.
package todo;
import java.util.stream.Stream;
public class Command {
private static final Command NO_OP = new Command("",new String[0]);
private final String command;
private final String[] arguments;
public Command(String command, String[] arguments){
this.command = command;
this.arguments = arguments;
}
public String getCommandString(){
return command;
}
public String[] getArguments(){
String[] argsCopy = new String[arguments.length];
System.arraycopy(arguments,0,argsCopy,0,arguments.length);
return argsCopy;
}
public static Command of(String commandString){
if(commandString == null){
return Command.NO_OP;
}
String[] split = commandString.split("\\(");
String command = split[0].trim();
String[] args;
if(split.length > 1) {
args = splitArguments(split[1]);
} else {
args = new String[0];
}
return new Command(command,args);
}
private static String[] splitArguments(String argumentString){
String[] args = argumentString.split("(,|\\)\\s*$)");
for(int i=0;i<args.length;i++){
args[i] = args[i].trim();
}
return args;
}
}
package todo;
import java.util.stream.Stream;
import java.util.List;
import java.util.ArrayList;
public class Item {
private String description;
private String[] categories;
public Item(String description){
this(description,new String[0]);
}
public Item(String description,String[] categories){
this.description = description;
this.categories = categories.clone();
}
public void setDescription(String description){
this.description = description;
}
public String getDescription(){
return description;
}
public String[] getCategories(){
return categories.clone();
}
@Override
public String toString(){
return description;
}
public boolean inCategory(String category){
return Stream.of(categories)
.anyMatch(c -> category.equals(c));
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<todo>
<item>
<description>A pixel is not a pixel is not a pixel</description>
<category>programming</category>
</item>
<item>
<description>The Scheme Programming Language</description>
<category>programming</category>
</item>
<item>
<description>Memory in C</description>
</item>
<item>
<description>Haskell's School of Music</description>
<category>programming</category>
<category>music</category>
</item>
<item>
<description>Algorithmic Symphonies from one line of code</description>
<category>programming</category>
<category>music</category>
</item>
<item>
<description>Modes in Folk Music</description>
<category>music</category>
</item>
<item>
<description>The use of the Melodic Minor Scale</description>
<category>music</category>
</item>
</todo>
package todo;
import java.util.Iterator;
import java.util.Collection;
import java.util.stream.Collectors;
public class ToDoList implements Iterable<Item>{
private final Collection<Item> items;
public ToDoList() {
items = new java.util.ArrayList<>();
}
public ToDoList(Collection<Item> items){
this.items = items;
}
public void addItem(Item item){
items.add(item);
}
public void deleteItem(Item item){
items.remove(item);
}
public void viewList(){
System.out.println(this);
}
private Collection<Item> inCategory(String category){
return items.stream()
.filter(i -> i.inCategory(category))
.collect(Collectors.toList());
}
public void viewList(String category){
System.out.println(ToDoList.toString(inCategory(category)));
}
public void renameItem(String from, String to){
items.stream()
.filter(i -> i.getDescription().equals(from))
.findFirst()
.ifPresent(i -> i.setDescription(to));
}
@Override
public Iterator<Item> iterator(){
return items.iterator();
}
@Override
public String toString(){
return ToDoList.toString(items);
}
private static String toString(Collection<Item> items){
return " - " + items.stream()
.map(Item::getDescription)
.collect(Collectors.joining("\n - "));
}
public static void main(String[] args) throws Exception{
String file = args[0];
ToDoList list = XmlToDoList.fromXmlList(XmlToDoList.readXml(file));
ToDoRepl.BASIC_REPL.startWith(list);
XmlToDoList.saveXml(XmlToDoList.toXmlList(list),file);
}
}
package todo;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiPredicate;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class ToDoRepl {
public final static ToDoRepl BASIC_REPL;
private final static Map<String,BiPredicate<String[],ToDoList>> BASIC_REPL_COMMMANDS;
static {
BASIC_REPL_COMMMANDS = new HashMap<>();
BASIC_REPL_COMMMANDS.put("addItem", (arguments,todo) -> {
if(arguments.length == 1){
todo.addItem(new Item(arguments[0]));
} else {
String[] categories = new String[arguments.length-1];
System.arraycopy(arguments,1,categories,0,categories.length);
todo.addItem(new Item(arguments[0],categories));
}
return true;
});
BASIC_REPL_COMMMANDS.put("deleteItem", (arguments,todo) -> {
if(arguments.length != 1){
ToDoRepl.reportError("deleteItem accepts exactly 1 argument");
} else {
todo.deleteItem(new Item(arguments[0]));
}
return true;
});
BASIC_REPL_COMMMANDS.put("viewList", (arguments,todo) -> {
if(arguments.length == 0){
todo.viewList();
} else {
for(int i=0;i<arguments.length;i++){
todo.viewList(arguments[i]);
}
}
return true;
});
BASIC_REPL_COMMMANDS.put("updateItem", (arguments,todo) -> {
if(arguments.length != 2){
ToDoRepl.reportError("updateItem accepts exactly 1 argument");
} else {
todo.renameItem(arguments[0],arguments[1]);
}
return true;
});
BASIC_REPL_COMMMANDS.put("exit", (arguments,todo) -> false);
BASIC_REPL = new ToDoRepl(BASIC_REPL_COMMMANDS);
}
public static void reportError(String message){
System.out.println("Error occurred in ToDoRepl environment: " + message);
}
private final Map<String,BiPredicate<String[],ToDoList>> myCommands;
public ToDoRepl(Map<String,BiPredicate<String[],ToDoList>> commands){
myCommands = commands;
}
public void startWith(ToDoList list){
try (
InputStreamReader inputReader = new InputStreamReader(System.in);
BufferedReader input = new BufferedReader(inputReader)
) {
boolean loopRunning = true;
String inputString;
do {
inputString = input.readLine();
Command parsedCommand = Command.of(inputString);
String commandString = parsedCommand.getCommandString();
String[] commandArguments = parsedCommand.getArguments();
if(myCommands.containsKey(commandString)){
loopRunning = myCommands.get(commandString).test(commandArguments,list);
}
} while(loopRunning);
} catch (IOException ioe){
System.out.println("IOException occurred in interactive mode!\n REPL environment has been quit!");
}
}
}
package todo;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.w3c.dom.*;
public class XmlToDoList {
public static ToDoList fromXmlList(Document xmlDocument){
ToDoList constructedList = new ToDoList();
Element listElement = xmlDocument.getDocumentElement();
if(listElement == null)
return constructedList;
NodeList itemNodes = listElement.getElementsByTagName("item");
for(int i = 0; i<itemNodes.getLength();i++){
Node itemNode = itemNodes.item(i);
constructedList.addItem(fromElement((Element) itemNode));
}
return constructedList;
}
private static Item fromElement(Element itemElement){
String description = itemElement.getElementsByTagName("description").item(0).getTextContent();
NodeList categoryNodes = itemElement.getElementsByTagName("category");
String[] categories = new String[categoryNodes.getLength()];
for(int i=0;i<categories.length;i++){
categories[i] = categoryNodes.item(i).getTextContent();
}
return new Item(description,categories);
}
public static Document toXmlList(ToDoList list) throws ParserConfigurationException {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document dom = builder.newDocument();
Element rootElement = dom.createElement("todo");
for(Item item:list){
Element itemElement = buildItemElement(dom,item);
rootElement.appendChild(itemElement);
}
dom.appendChild(rootElement);
return dom;
}
private static Element buildItemElement(Document dom,Item item){
Element itemElement = dom.createElement("item");
Element itemDescription = dom.createElement("description");
itemDescription.appendChild(dom.createTextNode(item.getDescription()));
itemElement.appendChild(itemDescription);
for(String str:item.getCategories()){
Element categoryElement = dom.createElement("category");
categoryElement.appendChild(dom.createTextNode(str));
itemElement.appendChild(categoryElement);
}
return itemElement;
}
public static void saveXml(Document xml, String file) throws TransformerException, IOException {
Transformer tr = TransformerFactory.newInstance().newTransformer();
tr.setOutputProperty(OutputKeys.INDENT, "yes");
tr.setOutputProperty(OutputKeys.METHOD, "xml");
tr.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
tr.transform(new DOMSource(xml),new StreamResult(new FileOutputStream(file)));
}
public static Document readXml(String file) throws ParserConfigurationException,SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom;
try {
dom = db.parse(file);
} catch (IOException ioe){
dom = db.newDocument();
}
return dom;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment