MenuBuilder DSL - Creating Menu Structures Easily
Learn how to use MenuBuilder DSL to create complex menu structures effortlessly without repetitive coding and errors. Simplify your code structure and enhance productivity today!
MenuBuilder DSL - Creating Menu Structures Easily
E N D
Presentation Transcript
Domain Specific Languages(Part 2) Based on http://martinfowler.com/dslwip
Using the JMenu API JMenuBar mb = new JMenuBar(); f.setJMenuBar(mb); JMenu file = new JMenu("File"); file.setMnemonic('F'); mb.add(file); JMenuItem open = new JMenuItem("Open"); open.setMnemonic('O'); open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)); open.addActionListener(new OpenCommand()); file.add(open); JMenuItem save = new JMenuItem("Save"); save.setMnemonic('S'); save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK)); save.addActionListener(new SaveCommand()); file.add(save); JMenuItem saveAs = new JMenuItem("Save As"); saveAs.setMnemonic('A'); saveAs.addActionListener(new SaveAsCommand()); file.add(saveAs);
Using the JMenu API (Cont.) JMenu edit = new JMenu("Edit"); edit.setMnemonic('E'); mb.add(edit); JMenuItem cut = new JMenuItem("Cut"); cut.setMnemonic('T'); cut.addActionListener(new CutCommand()); edit.add(cut); JMenuItem copy = new JMenuItem("Copy"); copy.setMnemonic('C'); copy.addActionListener(new CopyCommand()); edit.add(copy); JMenuItem paste = new JMenuItem("Paste"); paste.setMnemonic('P'); paste.addActionListener(new PasteCommand()); edit.add(paste);
Difficulties with JMenu • Repetition of the "current" menu variable • Code structure does not reflect menu structure • Tiny details – easy to get them wrong • A new menu item is created by Copy/Paste • Programmer often misses one of the adjustments
MenuBuilder w/o JSON • Two classes • Node • MenuBuilder • (See next 3 slides)
private static class Node { private final Map<String, Object> props = new HashMap<String, Object>(); private final List<Node> children = new ArrayList<Node>(); public JMenuItem create() { if (children.size() > 0) { JMenu result = new JMenu((String) get(NAME)); setShortcut(result); for (Node n : children) result.add(n.create()); return result; } JMenuItem result = new JMenuItem((String) get(NAME)); setShortcut(result); ActionListener al = (ActionListener) get(ACTION); if (al != null) result.addActionListener(al); return result; } private void setShortcut(JMenuItem result) { Character c = (Character) get(SHORTCUT); if (c != null) result.setMnemonic(c); } public void put(String key, Object value) { props.put(key, value); } private Object get(String key) { return props.get(key); } }
public class MenuBuilder { private Node node = new Node(); private MenuBuilder parent; public MenuBuilder() { this(null, ""); } private MenuBuilder(MenuBuilder parent, String name) { this.parent = parent; node.put(NAME, name); if (parent != null) parent.add(node); } public MenuBuilder child(String name) { return new MenuBuilder(this, name); } private void add(Node child) { node.children.add(child); } public MenuBuilder shortcut(char c) { node.put(SHORTCUT, c); return this; } ... }
public class MenuBuilder { ... public MenuBuilder action(ActionListener al) { node.put(ACTION, al); return this; } public MenuBuilder up() { return parent; } public JMenuBar build() { JMenuBar result = new JMenuBar(); for (Node n : node.children) result.add(n.create()); return result; } }
DSL Example • Read input file • Populate a relational database • Record per line Based on: http://martinfowler.com/articles/languageWorkbench.html http://www.infoq.com/presentations/domain-specific-languages
Input: Text #123456789012345678901234567890123456789012345678901234567890 PRCHFOWLER 10101MS0120050313 PRCHHOHPE 10201DX0320050315 PRCHJOHN 10301MR3720050329 ORDR10301MR99
Output: SQL Queries INSERT INTO Purchases (item_id,customer_id,date,amount) VALUES (10101MS,FOWLER,20050313,01) INSERT INTO Purchases (item_id,customer_id,date,amount) VALUES (10201DX,HOHPE,20050315,03) INSERT INTO Purchases (item_id,customer_id,date,amount) VALUES (10301MR,JOHN,20050329,37) INSERT INTO Orders (item_id,amount) VALUES (10301MR,99)
Naïve Solution public void run(Scanner sc) { while(sc.hasNext()) { String line = sc.nextLine(); if(line.startsWith("#")) continue; String code = line.substring(0, 4); if(code.equals("PRCH")) { String customerId = line.substring(4, 19).trim(); String itemId = line.substring(19, 26).trim(); String amount = line.substring(26, 28).trim(); String date = line.substring(28, 36).trim(); purchase(customerId, itemId, amount, date); } else if(code.equals("ORDR")) { String itemId = line.substring(4, 11).trim(); String amount = line.substring(11, 13).trim(); order(itemId, amount); } } } public void purchase(String c, String i, String a, String d) { ... } public void order(String i, String a) { ... }
DSL-based Solution new Processor("PRCH", "Purchases") .field("item_id", 19, 26) .field("customer_id", 4, 19) .field("date", 28, 36) .field("amount", 26, 28) .addTo(processors); new Processor("ORDR", "Orders") .field("item_id", 4, 11) .field("amount", 11, 13) .addTo(processors);