. Java Design Patterns . Java Design Patterns Interpreter

Java Design Patterns Interpreter

Interpreter Overview

Define a macro language and syntax, parsing input into objects which perform the correct opertaions.

DvdInterpreterClient.java - the Client

import java.util.StringTokenizer;

public class DvdInterpreterClient {  
   DvdInterpreterContext dvdInterpreterContext; 
   
   public DvdInterpreterClient(
     DvdInterpreterContext dvdInterpreterContext) {
       this.dvdInterpreterContext = dvdInterpreterContext;
   }
    
   // expression syntax:
   // show title | actor [for actor | title ]
   public String interpret(String expression) {
       StringBuffer result = new StringBuffer("Query Result: ");
       
       String currentToken;
       StringTokenizer expressionTokens = 
         new StringTokenizer(expression);
       
       char mainQuery = ' ';
       char subQuery = ' ';
       boolean forUsed = false;
       String searchString = null;
       boolean searchStarted = false;
       boolean searchEnded = false;
       
       while (expressionTokens.hasMoreTokens())
       {
           currentToken = expressionTokens.nextToken();
           if (currentToken.equals("show")) {
               continue;
               //show in all queries, not really used
           } else if (currentToken.equals("title")) {
               if (mainQuery == ' ') {
                   mainQuery = 'T';
               } else {
                   if ((subQuery == ' ') && (forUsed)) {
                       subQuery = 'T';
                   } 
               }
           } else if (currentToken.equals("actor")) {
               if (mainQuery == ' ') {
                   mainQuery = 'A';
               } else {
                   if ((subQuery == ' ') && (forUsed)) {
                       subQuery = 'A';
                   }
               } 
           } else if (currentToken.equals("for")) {
               forUsed = true;
           } else if ((searchString == null) && 
                      (subQuery != ' ') && 
                      (currentToken.startsWith("<"))) {
                 searchString = currentToken;
                 searchStarted = true;
                 if (currentToken.endsWith(">")) {
                     searchEnded = true;
                 }
           } else if ((searchStarted) && (!searchEnded)) {
               searchString = searchString + " " + currentToken;
               if (currentToken.endsWith(">")) {
                   searchEnded = true;
               }
           }
       }

       if (searchString != null) {
           searchString = 
             searchString.substring(1,(searchString.length() - 1));
             //remove <>
       }
       
       DvdAbstractExpression abstractExpression;
       
       switch (mainQuery) {
           case 'A' :  {
               switch (subQuery) {
                   case 'T' : {
                       abstractExpression = 
                         new DvdActorTitleExpression(searchString);
                       break;
                   }
                   default : {
                       abstractExpression = 
                         new DvdActorExpression();
                       break;
                   }
               }
               break;
           }      
           case 'T' : {
               switch (subQuery) {
                   case 'A' : {
                       abstractExpression = 
                         new DvdTitleActorExpression(searchString);
                       break;
                   }
                   default : {
                       abstractExpression = new DvdTitleExpression();
                       break;
                   }
               }
               break;
           }            
           
           default : return result.toString();
       } 
       
       
       result.append(
         abstractExpression.interpret(dvdInterpreterContext));
       
       return result.toString();
   }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdInterpreterContext.java - The Context

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdInterpreterContext {
   private ArrayList titles = new ArrayList(); 
   private ArrayList actors = new ArrayList();
   private ArrayList titlesAndActors = new ArrayList();
   
   public void addTitle(String title) {
       titles.add(title);
   }
   public void addActor(String actor) {
       actors.add(actor);
   }
   public void addTitleAndActor(TitleAndActor titleAndActor) {
       titlesAndActors.add(titleAndActor);
   }
   
   public ArrayList getAllTitles() {
       return titles;
   }
   public ArrayList getAllActors() {
       return actors;
   }
   public ArrayList getActorsForTitle(String titleIn) {
       ArrayList actorsForTitle = new ArrayList();
       TitleAndActor tempTitleAndActor;
       ListIterator titlesAndActorsIterator = 
         titlesAndActors.listIterator();
       while (titlesAndActorsIterator.hasNext()) {
           tempTitleAndActor = 
             (TitleAndActor)titlesAndActorsIterator.next();
           if (titleIn.equals(tempTitleAndActor.getTitle())) {
               actorsForTitle.add(tempTitleAndActor.getActor());
           }
       }
       return actorsForTitle;
   }
   public ArrayList getTitlesForActor(String actorIn) {
       ArrayList titlesForActor = new ArrayList();
       TitleAndActor tempTitleAndActor;
       ListIterator actorsAndTitlesIterator = 
         titlesAndActors.listIterator();
       while (actorsAndTitlesIterator.hasNext()) {
           tempTitleAndActor = 
             (TitleAndActor)actorsAndTitlesIterator.next();
           if (actorIn.equals(tempTitleAndActor.getActor())) {
               titlesForActor.add(tempTitleAndActor.getTitle());
           }
       }
       return titlesForActor;
   }   
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdAbstractExpression.java - The Abstract Expression

public abstract class DvdAbstractExpression {
   public abstract String interpret(
     DvdInterpreterContext dvdInterpreterContext);
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdActorExpression.java - One Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdActorExpression extends DvdAbstractExpression {  
   public String interpret(DvdInterpreterContext dvdInterpreterContext) {
       ArrayList actors = dvdInterpreterContext.getAllActors();
       ListIterator actorsIterator = actors.listIterator();
       StringBuffer titleBuffer = new StringBuffer("");
       boolean first = true;
       while (actorsIterator.hasNext()) {
           if (!first) {
               titleBuffer.append(", ");
           } else {
               first = false;
           }
           titleBuffer.append((String)actorsIterator.next());
       }
       return titleBuffer.toString();
   }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdActorTitleExpression.java - Two Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdActorTitleExpression extends DvdAbstractExpression {
   String title;
   
   public DvdActorTitleExpression(String title) {
       this.title = title;
   }
    
   public String interpret(DvdInterpreterContext dvdInterpreterContext) {
       ArrayList actorsAndTitles = 
           dvdInterpreterContext.getActorsForTitle(title);
       ListIterator actorsAndTitlesIterator = 
           actorsAndTitles.listIterator();
       StringBuffer actorBuffer = new StringBuffer("");
       boolean first = true;
       while (actorsAndTitlesIterator.hasNext()) {
           if (!first) {
               actorBuffer.append(", "); 
           } else {
               first = false;
           }
           actorBuffer.append((String)actorsAndTitlesIterator.next());
       }
       return actorBuffer.toString();
   }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdTitleExpression.java - Three Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdTitleExpression extends DvdAbstractExpression {  
   public String interpret(DvdInterpreterContext 
                           dvdInterpreterContext) {
       ArrayList titles = dvdInterpreterContext.getAllTitles();
       ListIterator titlesIterator = titles.listIterator();
       StringBuffer titleBuffer = new StringBuffer("");
       boolean first = true;
       while (titlesIterator.hasNext()) {
           if (!first) {
               titleBuffer.append(", ");
           } else {
               first = false;
           }    
           titleBuffer.append((String)titlesIterator.next());
       }
       return titleBuffer.toString();
   }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

DvdTitleActorExpression.java - Four Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdTitleActorExpression extends DvdAbstractExpression {  
   String title;
   
   public DvdTitleActorExpression(String title) {
       this.title = title;
   }
    
   public String interpret(DvdInterpreterContext dvdInterpreterContext) {
       ArrayList titlesAndActors = 
           dvdInterpreterContext.getTitlesForActor(title);
       ListIterator titlesAndActorsIterator = 
           titlesAndActors.listIterator();
       StringBuffer titleBuffer = new StringBuffer("");
       boolean first = true;
       while (titlesAndActorsIterator.hasNext()) {
           if (!first) {
               titleBuffer.append(", ");
           } else {
               first = false;
           }
           titleBuffer.append((String)titlesAndActorsIterator.next());
       }
       return titleBuffer.toString();
   }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

TitleAndActor.java - A Helper Class

public class TitleAndActor {
    private String title;
    private String actor;
    public TitleAndActor(String title, String actor) {
        this.title = title;
        this.actor = actor;
    }
    public String getTitle() {return this.title;}
    public String getActor() {return this.actor;}
}     
download source, use right-click and "Save Target As..." to save with a .java extension.

TestDvdInterpreter.java - testing the Interpreter

class TestDvdInterpreter {
    
   public static void main(String[] args) {
       DvdInterpreterContext dvdInterpreterContext = 
         new DvdInterpreterContext();
       dvdInterpreterContext.addTitle("Caddy Shack");
       dvdInterpreterContext.addTitle("Training Day");
       dvdInterpreterContext.addTitle("Hamlet");

       dvdInterpreterContext.addActor("Ethan Hawke");
       dvdInterpreterContext.addActor("Denzel Washington");
       
       dvdInterpreterContext.addTitleAndActor(
         new TitleAndActor("Hamlet", "Ethan Hawke"));
       dvdInterpreterContext.addTitleAndActor(
         new TitleAndActor("Training Day", "Ethan Hawke"));
       dvdInterpreterContext.addTitleAndActor(
         new TitleAndActor("Caddy Shack", "Ethan Hawke"));
       dvdInterpreterContext.addTitleAndActor(
         new TitleAndActor("Training Day", "Denzel Washington"));
       
       DvdInterpreterClient dvdInterpreterClient = 
         new DvdInterpreterClient(dvdInterpreterContext);
       
       System.out.println(
         "interpreting show actor: " + 
          dvdInterpreterClient.interpret(
            "show actor"));
       System.out.println(
          "interpreting show actor for title : " + 
           dvdInterpreterClient.interpret(
             "show actor for title "));
       System.out.println(
          "interpreting show title: " + 
           dvdInterpreterClient.interpret(
             "show title")); 
       System.out.println(
          "interpreting show title for actor : " + 
           dvdInterpreterClient.interpret(
             "show title for actor "));
   }
}      
download source, use right-click and "Save Target As..." to save with a .java extension.

Test Results

interpreting show actor: 
  Query Result: Ethan Hawke, Denzel Washington
interpreting show actor for title : 
  Query Result: Ethan Hawke, Denzel Washington
interpreting show title: 
  Query Result: Caddy Shack, Training Day, Hamlet
interpreting show title for actor : 
  Query Result: Hamlet, Training Day, Caddy Shack

UML

UML for Interpreter

References

online

Portland Pattern Repository

Books

Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
Java Design Patterns - A Tutorial by James W. Cooper
Sign In
to add your own comment
Comment by markmontymark Rate this Comment

replace the '<' char with &lt; and the '>' char with &gt; to display properly in HTML

Comment by archive Rate this Comment

I realy appreciate the Java Patterns on your site. Since I like to play with the examples I simply copied it into text fils and compiled them. I found a few minor problems you may want to know about:

- null pointer exception for second example, I did
not yet try to find out what the real reason is.

interpreting show actor: Query Result: Ethan
Hawke,
Denzel Washington
Exception in thread "main"
java.lang.NullPointerException at
DvdInterpreterContext.getActorsForTitle(DvdInterpreterContext.java:24)
at
DvdActorTitleExpression.interpret(DvdActorTitleExpression.java:12)
at
DvdInterpreterClient.interpret(DvdInterpreterClient.java:106)
at
TestDvdInterpreter.main(TestDvdInterpreter.java:28)

Comment by archive Rate this Comment

Ah, I also see now why the Interpreter example
gets a null pointer exception:

two lines in main() should contain the < >
construction:
dvdInterpreterClient.interpret("show actor for
title <Training Day>"));
...
dvdInterpreterClient.interpret("show title for actor
<Ethan Hawke>"));

However, since you show it in HTML, the browser is
not displaying it since it interprets them as
tags (which it does not know how to display)