public class RestCompilePanel extends Composite implements WindowResizeListener {
  public static VerticalPanel restCompilePanel = new VerticalPanel();
  private static VerticalPanel restCompileArea = new VerticalPanel();
  public static HorizontalPanel buttonPanel = new HorizontalPanel();
  public static TextArea codeTextArea = new TextArea();  
  public static HorizontalPanel compilePanel = new HorizontalPanel();
  private static VerticalPanel requestClassesPanel = new VerticalPanel();
  private static ListBox paramsListBox = new ListBox();
  private static VerticalPanel namingParamPanel = new VerticalPanel();
  private static HorizontalPanel namingDepthPanel = new HorizontalPanel();
  public static String paramToUseForName = "";
  private static ScrollPanel usedClassesPanel = new ScrollPanel();
  private static RadioButton useParameterAsNameRadio = new RadioButton("paramOrEndpoint", GuiFactory.strings.useParam());
  private static RadioButton useEndpointAsNameRadio = new RadioButton("paramOrEndpoint", GuiFactory.strings.useEndpoint());
  public static final String[] commonOpParamNames = {"operation", "method", "function", "request", "call"};
  
  public RestCompilePanel() {
    Window.addWindowResizeListener(this);
    
    restCompilePanel.setStyleName("restDescribe-restCompilePanel");
    restCompilePanel.setWidth("100%");       
        
    HTML restCompileHeader = new HTML ("<h2>" + GuiFactory.strings.restCompile() + "</h2>");
    restCompilePanel.add(restCompileHeader);    
    
    restCompileArea.setStyleName("restDescribe-restCompileArea");
    restCompilePanel.add(restCompileArea);    
    
    HorizontalPanel containerPanel = new HorizontalPanel();
    HorizontalPanel languagesPanel = new HorizontalPanel();
    containerPanel.add(languagesPanel);
    VerticalPanel reviewPanel = new VerticalPanel();
    containerPanel.add(new HTML("&nbsp;&nbsp;"));
    containerPanel.add(reviewPanel);    
    restCompileArea.add(containerPanel);
         
    final Button phpLink = new Button("<nobr>" + imageHtml("php.png") + CodeGenerator.php5 + "</nobr>");
    phpLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        generateCode(CodeGenerator.php5);
      }     
    });
    languagesPanel.add(phpLink);        
                     
    final Button rubyLink = new Button("<nobr>" + imageHtml("ruby.png") + CodeGenerator.ruby + "</nobr>");    
    rubyLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        generateCode(CodeGenerator.ruby);
      }     
    });
    languagesPanel.add(rubyLink);   
     
    final Button pythonLink = new Button("<nobr>" + imageHtml("python.png") + CodeGenerator.python + "</nobr>");
    pythonLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        generateCode(CodeGenerator.python);
      }     
    });
    languagesPanel.add(pythonLink);   

    final Button javaLink = new Button("<nobr>" + imageHtml("java.png") + CodeGenerator.java + "</nobr>");
    javaLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        generateCode(CodeGenerator.java);
      }     
    });
    languagesPanel.add(javaLink);   

    final Button csharpLink = new Button("<nobr>" + imageHtml("csharp.png") + CodeGenerator.csharp + "</nobr>");
    csharpLink.setEnabled(false);
    csharpLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        generateCode(CodeGenerator.csharp);
      }     
    });    
    languagesPanel.add(csharpLink);   
    
    Hyperlink reviewWadl = new Hyperlink(GuiFactory.strings.reviewWadl(), true, "");
    reviewWadl.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        WadlPanel.wadlPreviewButton.click();
      }
    });    
    reviewPanel.add(reviewWadl);
    
    reviewPanel.add(new HTML("<br />"));
    
    Hyperlink backLink = new Hyperlink(GuiFactory.strings.backToDescribe(), true, "");
    backLink.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        GuiFactory.toggleMode(GuiFactory.restDescribe);
      }
    });    
    reviewPanel.add(backLink);

    restCompileArea.add(new HTML("&nbsp;<br />"));
    restCompileArea.add(compilePanel);
    compilePanel.setVisible(false);           
    codeTextArea.setText("");    
    compilePanel.add(codeTextArea);  
    compilePanel.add(new HTML("&nbsp;"));
    VerticalPanel codeOptionsPanel = new VerticalPanel();
    compilePanel.add(codeOptionsPanel);
    compilePanel.setCellVerticalAlignment(codeOptionsPanel, HasVerticalAlignment.ALIGN_BOTTOM);
    
    // source for class names    
    useParameterAsNameRadio.setChecked(!SettingsDialog.useEndpointAsName);
    useParameterAsNameRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        SettingsDialog.useEndpointAsName = !useParameterAsNameRadio.isChecked();   
        toggleNamingPanels(SettingsDialog.useEndpointAsName);
      }      
    });
        
    useEndpointAsNameRadio.setChecked(SettingsDialog.useEndpointAsName);
    useEndpointAsNameRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        SettingsDialog.useEndpointAsName = useEndpointAsNameRadio.isChecked();
        toggleNamingPanels(SettingsDialog.useEndpointAsName);
      }      
    });
    
    VerticalPanel radioContainerPanel = new VerticalPanel();
    radioContainerPanel.add(new HTML("<h2>" + GuiFactory.strings.className() + ":</h2>"));   
    codeOptionsPanel.add(radioContainerPanel);
        
    final TextBox namingDepthTextBox = new TextBox();    
    namingDepthTextBox.setWidth("2em");
    namingDepthTextBox.setText(SettingsDialog.namingDepthLevel + "");
    namingDepthTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        try {
          SettingsDialog.namingDepthLevel =
            Integer.parseInt(namingDepthTextBox.getText());
          namingDepthTextBox.removeStyleName("restDescribe-error");
          if (SettingsDialog.namingDepthLevel == 0) {
            namingDepthTextBox.setStyleName("restDescribe-error");
          }
        } catch (NumberFormatException e) {    
          namingDepthTextBox.setStyleName("restDescribe-error");
        }                  
      }      
    });            
       
    codeOptionsPanel.add(useEndpointAsNameRadio);
    codeOptionsPanel.add(namingDepthPanel);
    namingDepthPanel.add(new HTML("&nbsp;"));
    namingDepthPanel.add(namingDepthTextBox);
    namingDepthPanel.add(new HTML(GuiFactory.strings.namingDepth()));    
        
    codeOptionsPanel.add(useParameterAsNameRadio);
    codeOptionsPanel.add(namingParamPanel);            
    namingParamPanel.add(paramsListBox);    
    paramsListBox.setWidth("12em");
    paramsListBox.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        if (paramsListBox.getItemCount() > 0) {
          paramToUseForName = paramsListBox.getValue(paramsListBox.getSelectedIndex());
        }
      }      
    });    
    
    toggleNamingPanels(SettingsDialog.useEndpointAsName);
    
    Button recompileButton = new Button(GuiFactory.strings.recompile());
    recompileButton.setWidth("12em");
    codeOptionsPanel.add(recompileButton);
    recompileButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        if (CodeGenerator.language.equals(CodeGenerator.java)) {
          javaLink.click();
        }
        else if (CodeGenerator.language.equals(CodeGenerator.php5)) {
          phpLink.click();
        } 
        else if (CodeGenerator.language.equals(CodeGenerator.python)) {
          pythonLink.click();
        }
        else if (CodeGenerator.language.equals(CodeGenerator.csharp)) {
          csharpLink.click();
        }
        else if (CodeGenerator.language.equals(CodeGenerator.ruby)) {
          rubyLink.click();
        }
      }
    });
        
    VerticalPanel requestClassesContainerPanel = new VerticalPanel();
    requestClassesContainerPanel.add(new HTML("<br />"));
    requestClassesContainerPanel.add(new HTML("<h2>" + GuiFactory.strings.generatedClasses() + ":</h2>"));    
    usedClassesPanel.add(requestClassesPanel); 
    usedClassesPanel.setStyleName("restDescribe-classNamesPanel");
    requestClassesContainerPanel.add(usedClassesPanel);
    
    codeOptionsPanel.add(requestClassesContainerPanel);   
    
    onWindowResized(Window.getClientWidth(), Window.getClientHeight());
        
    Button okButton = new Button(GuiFactory.strings.ok());
    okButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        GuiFactory.toggleMode(GuiFactory.restDescribe);
      }
    });
    
    Button selectAllButton = new Button(GuiFactory.strings.selectAll());
    selectAllButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        selectAll(codeTextArea);
      }
    });    
    
    restCompileArea.add(new HTML("<br />"));    
    buttonPanel.add(okButton);    
    buttonPanel.add(selectAllButton);    
    restCompileArea.add(buttonPanel);
    restCompileArea.setCellHorizontalAlignment(buttonPanel, HasHorizontalAlignment.ALIGN_CENTER);
    
    initWidget(restCompilePanel);
  }

  /**
   * @param useEndpointAsName
   */
  public static void toggleNamingPanels(boolean useEndpointAsName) {    
    namingDepthPanel.setVisible(useEndpointAsName);
    namingParamPanel.setVisible(!useEndpointAsName);
    useEndpointAsNameRadio.setChecked(useEndpointAsName);
    useParameterAsNameRadio.setChecked(!useEndpointAsName);   
  }

  /**
   * 
   */
  private static void listUsedClassNames() {
    Iterator classNameIterator = CodeGenerator.usedClassNames.iterator();
    requestClassesPanel.clear();
    while(classNameIterator.hasNext()) {      
      final String className = (String) classNameIterator.next();
      Hyperlink hyperlink = new Hyperlink("<nobr><img align=\"absmiddle\" src=\"./images/details.png\" />" + className + "</nobr>", true, "");
      hyperlink.addClickListener(new ClickListener() {
        public void onClick(Widget sender) {
          int pos = codeTextArea.getText().indexOf(className);
          codeTextArea.setCursorPos(pos);          
          codeTextArea.setSelectionRange(pos, className.length());
        }        
      });
      requestClassesPanel.add(hyperlink);      
    }    
  }
  
  private static void listParams() {
    if (Analyzer.application != null &&
        Analyzer.application.getResources() != null &&
        Analyzer.application.getResources().getAllResources() != null) {
      paramsListBox.clear(); 
      addParamsToListBox(Analyzer.application.getResources().getAllResources(), true);      
    }
  }

  /**
   * @param language
   */
  protected static void generateCode(String language) {
    CodeGenerator codeGenerator = new CodeGenerator(Analyzer.application);    
    buttonPanel.setVisible(true);
    compilePanel.setVisible(true);    
    listParams();    
    toggleNamingPanels(SettingsDialog.useEndpointAsName);
    String code = codeGenerator.generate(language);
    codeTextArea.setText(code);
    listUsedClassNames();
  }

  private static void guessNamingParameter() {      
    for (int i = 0; i < paramsListBox.getItemCount(); i++) {
      for (int j = 0; j < commonOpParamNames.length; j++) {
        if (paramsListBox.getValue(i).equalsIgnoreCase(commonOpParamNames[j])) {
          paramsListBox.setSelectedIndex(i);
          paramToUseForName = paramsListBox.getValue(i);
          return;      
        }
      }
    }        
  }
  /* (non-Javadoc)
   * @see com.google.gwt.user.client.WindowResizeListener#onWindowResized(int, int)
   */
  public void onWindowResized(int width, int height) {
    restCompileArea.setWidth(Math.floor(0.97 * width) + "px");
    codeTextArea.setWidth(Math.floor(0.7 * width) + "px");
    codeTextArea.setHeight(Math.floor(0.5 * height) + "px");
    usedClassesPanel.setHeight(Math.floor(0.18 * height) + "px");
    usedClassesPanel.setWidth(Math.floor(0.2 * width) + "px");
  }
  
  private static String imageHtml(String src) {
    return "<img src=\"./images/" + src + "\" border=\"0\" height=\"30\" width=\"30\" align=\"absmiddle\" style=\"padding-left:20px; padding-right:5px;\" />";
  }
  private static void selectAll(TextArea textArea) {
    textArea.setSelectionRange(0, textArea.getText().length());    
  }
  
  private static void addParamsToListBox(Vector allResources, boolean firstCall) {
    // do this the first time only
    if (firstCall) {      
      if (Analyzer.application != null) {
        ApplicationNode application = Analyzer.application;      
        if (!application.getAllParams().isEmpty()) {          
          examineParams(application.getAllParams());
          return;
        }    
        // if we still found nothing, check the referenced methods
        if (!application.getAllMethods().isEmpty()) {          
          Vector allMethods = application.getAllMethods();
          Iterator allMethodsIterator = allMethods.iterator();
          while (allMethodsIterator.hasNext()) {
            MethodNode method = (MethodNode) allMethodsIterator.next();                    
            if (method.getRequest() != null) {              
              RequestNode request = method.getRequest();                        
              if (!request.getAllParams().isEmpty()) {                
                examineParams(request.getAllParams());  
                return;
              }
            }
          }
        }
      }
    }  
    // do this every time
    Iterator allResourcesIterator = allResources.iterator();
    while(allResourcesIterator.hasNext()) {
      ResourceNode resource = (ResourceNode) allResourcesIterator.next();      
      if (!resource.getAllMethods().isEmpty()) {
        Vector allMethods = resource.getAllMethods();
        Iterator allMethodsIterator = allMethods.iterator();
        while(allMethodsIterator.hasNext()) {
          MethodNode method = (MethodNode) allMethodsIterator.next();          
          if (method.getRequest() != null) {
            RequestNode request = method.getRequest();                    
            if (!request.getAllParams().isEmpty()) {             
              examineParams(request.getAllParams());
              return;
            }
          }          
        }
      }    
      // recursive call for inner resources (a resource in a resource)
      addParamsToListBox(resource.getAllResources(), false);      
    }
  }   

  /**
   * @param allParams
   */
  private static void examineParams(Vector allParams) {
    Iterator allParamsIterator = allParams.iterator();
    int i = 0;
    while(allParamsIterator.hasNext()) {
      ParamNode param = (ParamNode) allParamsIterator.next();      
      if (param.getValue().length() > 0) {
        paramsListBox.addItem(param.getName() + " (\"" + param.getValue() + "\")", param.getName());
        if (paramToUseForName.equalsIgnoreCase(param.getName())) {
          paramsListBox.setSelectedIndex(i);
          return;
        }
      }
      else {
        paramsListBox.addItem("[N/A] " + param.getName() + " (N/A)", param.getName());        
      }
      i++;      
    }
    // if no paramToUseForName was given, try to guess it
    if (paramToUseForName.equals("")) {
      guessNamingParameter(); 
      // if one was found, use it
      if (paramToUseForName.length() > 0) {
        SettingsDialog.useEndpointAsName = false;
        useParameterAsNameRadio.setChecked(true);
      }
      // if nothing found, use the endpoint as name
      else {
        useEndpointAsNameRadio.setChecked(true);
      }
    }       
  }
} public class SettingsDialog {
  public static boolean alwaysShowDetails = false;
  public static boolean alwaysShowDetailsTemp = alwaysShowDetails;
  public static boolean treeItemsAlwaysOpen = true;
  public static boolean treeItemsAlwaysOpenTemp = treeItemsAlwaysOpen;
  public static int requestTimeoutSeconds = 180;
  public static int namingDepthLevel = 1;
  public static String pathToDiscoverer = "./resources/Discoverer.php5";
  public static String pathToJsonConverter = "./resources/XML2JSON.php5";
  public static boolean useEndpointAsName = true;
  public static String separationCharacter = "_";
  public static boolean useSeparationCharacter = false;
  public static boolean useSeparationCharacterTemp = useSeparationCharacter;
  public static String classDefaultSuffix = "";
  public static int indentWidth = 2;
  public static boolean indentWithSpaces = true; 
  public static String templateSuffix = ""; //"_TEMPLATE";  
  private static final String confirm_de = "<a href=\"RestDescribe.html?locale=de\">" + GuiFactory.strings.confirmAndRestart() + "</a>";   
  private static final String confirm_enUS = "<a href=\"RestDescribe.html?locale=en\">" + GuiFactory.strings.confirmAndRestart() + "</a>";
  private static final String confirm_ca = "<a href=\"RestDescribe.html?locale=ca\">" + GuiFactory.strings.confirmAndRestart() + "</a>";

  /**
   * Creates the settings dialog
   */
  public static void show() {
    String panelHeight = "3em";
    String panelWidthLeft = "15em";
    String panelWidthRight = "20em";
    String textBoxWidth = "8em";
    final DialogBox dialogBox = new DialogBox();    
    dialogBox.setText(GuiFactory.strings.settingsLink());    
       
    VerticalPanel settingsPanel = new VerticalPanel();   
    TabPanel tabPanel = new TabPanel();   
        
    final ListBox languageListBox = new ListBox();   
    languageListBox.addItem(GuiFactory.strings.english_US());
    languageListBox.addItem(GuiFactory.strings.german());
    languageListBox.addItem(GuiFactory.strings.catalan());
        
    VerticalPanel generalPanel = new VerticalPanel(); 
     
    HorizontalPanel languagePanel = new HorizontalPanel();   
    languagePanel.setHeight(panelHeight);
    HorizontalPanel languagePanelLeft = new HorizontalPanel();
    HorizontalPanel languagePanelRight = new HorizontalPanel();
     
    languagePanelLeft.setWidth(panelWidthLeft);
    languagePanelLeft.add(new HTML("<b>" + GuiFactory.strings.language() + "</b>"));   
    languagePanelRight.setWidth(panelWidthRight);
    languagePanelRight.add(new HTML(GuiFactory.strings.displayRestDescribe() + ":&nbsp;"));
    languagePanelRight.add(languageListBox);   
        
    languagePanel.add(languagePanelLeft);
    languagePanel.add(languagePanelRight);   
    generalPanel.add(languagePanel);
     
    final HorizontalPanel confirmLangChange =  new HorizontalPanel();
    confirmLangChange.setVisible(false);
    confirmLangChange.add(new HTML(GuiFactory.strings.cautionChangesGetLost() + "&nbsp;"));
       
    final HTML confirmLink = new HTML("");
    confirmLangChange.add(confirmLink);
    confirmLangChange.add(new HTML("."));   
    generalPanel.add(confirmLangChange);   
    languageListBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {       
        updateAndDisplayConfirmLink(languageListBox.getItemText(languageListBox.getSelectedIndex()), confirmLink, confirmLangChange);
      }
    });
    languageListBox.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        updateAndDisplayConfirmLink(languageListBox.getItemText(languageListBox.getSelectedIndex()), confirmLink, confirmLangChange);
      }     
    });
     
    final CheckBox detailsCheckBox = new CheckBox();
    detailsCheckBox.setChecked(alwaysShowDetails);
    detailsCheckBox.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        if (detailsCheckBox.isChecked()) {
          alwaysShowDetailsTemp = true;        
        }
        else {
          alwaysShowDetailsTemp = false;
        }
      }
    });
       
    final CheckBox treesCheckBox = new CheckBox();
    treesCheckBox.setChecked(treeItemsAlwaysOpen);
    treesCheckBox.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        if (treesCheckBox.isChecked()) {
          treeItemsAlwaysOpenTemp = true;        
        }
        else {
          treeItemsAlwaysOpenTemp = false;
        }
      }
    });
    
    final HorizontalPanel miniSepTextPanel = new HorizontalPanel();
    final CheckBox useSeparationCharacterCheckBox = new CheckBox();
    useSeparationCharacterCheckBox.setChecked(useSeparationCharacter);
    useSeparationCharacterCheckBox.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        if (useSeparationCharacterCheckBox.isChecked()) {
          useSeparationCharacterTemp = true;        
        }
        else {
          useSeparationCharacterTemp = false;
        }
        miniSepTextPanel.setVisible(useSeparationCharacterTemp);
      }
    });
     
    final TextBox timeoutSecondsTextBox = new TextBox();
    timeoutSecondsTextBox.setText(Integer.toString(requestTimeoutSeconds));
    timeoutSecondsTextBox.setWidth(panelHeight);
    timeoutSecondsTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        try {
          requestTimeoutSeconds = Integer.parseInt(timeoutSecondsTextBox.getText());
          timeoutSecondsTextBox.removeStyleName("restDescribe-error");
        } catch (NumberFormatException e) {    
          timeoutSecondsTextBox.setStyleName("restDescribe-error");
        }
      }     
    });   
    
    miniSepTextPanel.setVisible(useSeparationCharacter);
    final TextBox separationCharacterTextBox = new TextBox();    
    separationCharacterTextBox.setText(separationCharacter);
    separationCharacterTextBox.setWidth(panelHeight);
    separationCharacterTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        separationCharacter = separationCharacterTextBox.getText();
      }     
    });
     
    final TextBox namingDepthTextBox = new TextBox();
    namingDepthTextBox.setText(Integer.toString(namingDepthLevel));
    namingDepthTextBox.setWidth(panelHeight);
    namingDepthTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        try {
          namingDepthLevel = Integer.parseInt(namingDepthTextBox.getText());
          namingDepthTextBox.removeStyleName("restDescribe-error");
          if (SettingsDialog.namingDepthLevel == 0) {
            namingDepthTextBox.setStyleName("restDescribe-error");
          }
        } catch (NumberFormatException e) {    
          namingDepthTextBox.setStyleName("restDescribe-error");
        }
      }     
    });
    
    final RadioButton useParameterAsNameRadio = new RadioButton("paramOrEndpoint", GuiFactory.strings.useParam());
    useParameterAsNameRadio.setChecked(!useEndpointAsName);
    useParameterAsNameRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        useEndpointAsName = !useParameterAsNameRadio.isChecked();        
      }      
    });
    
    final RadioButton useEndpointAsNameRadio = new RadioButton("paramOrEndpoint", GuiFactory.strings.useEndpoint());
    useEndpointAsNameRadio.setChecked(useEndpointAsName);
    useEndpointAsNameRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        useEndpointAsName = useEndpointAsNameRadio.isChecked();
      }      
    });
    
    final TextBox indentWidthTextBox = new TextBox();
    indentWidthTextBox.setWidth(panelHeight);
    indentWidthTextBox.setText(indentWidth + "");
    indentWidthTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        try {
          indentWidth = Integer.parseInt(indentWidthTextBox.getText());
          indentWidthTextBox.removeStyleName("restDescribe-error");
          if (SettingsDialog.indentWidth == 0) {
            indentWidthTextBox.setStyleName("restDescribe-error");
          }
        } catch (NumberFormatException e) {    
          indentWidthTextBox.setStyleName("restDescribe-error");
        }        
      }      
    });
    
    final HorizontalPanel indentMiniPanel = new HorizontalPanel();
    final RadioButton indentWithSpacesRadio = new RadioButton("indent", GuiFactory.strings.indentSpaces());
    indentWithSpacesRadio.setChecked(indentWithSpaces);
    indentWithSpacesRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        indentWithSpaces = indentWithSpacesRadio.isChecked();
        indentMiniPanel.setVisible(true);
      }      
    });
    
    final RadioButton indentWithTabsRadio = new RadioButton("indent", GuiFactory.strings.indentTabs());
    indentWithTabsRadio.setChecked(!indentWithSpaces);
    indentWithTabsRadio.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {        
        indentWithSpaces = !indentWithTabsRadio.isChecked();
        indentMiniPanel.setVisible(false);
      }      
    });
    
    final TextBox classSuffixTextBox = new TextBox();
    classSuffixTextBox.setText(classDefaultSuffix);
    classSuffixTextBox.setWidth(textBoxWidth);
    classSuffixTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {
        classDefaultSuffix = classSuffixTextBox.getText();        
      }
    });
     
    final TextBox pathToDiscovererTextBox = new TextBox();
    pathToDiscovererTextBox.setText(pathToDiscoverer);
    pathToDiscovererTextBox.setWidth(textBoxWidth);
    pathToDiscovererTextBox.addChangeListener(new ChangeListener() {
      public void onChange(Widget sender) {        
        pathToDiscoverer = pathToDiscovererTextBox.getText();        
      }     
    });
    
    // preferences
    VerticalPanel preferencesPanel = new VerticalPanel(); 
    preferencesPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
     
    // details
    HorizontalPanel detailsPanel = new HorizontalPanel(); 
    detailsPanel.setHeight(panelHeight);
    HorizontalPanel detailsPanelLeft = new HorizontalPanel();
    HorizontalPanel detailsPanelRight = new HorizontalPanel();   
    detailsPanelLeft.setWidth(panelWidthLeft);
    detailsPanelLeft.add(new HTML("<b>" + GuiFactory.strings.details() + "</b>"));
    detailsPanelRight.setWidth(panelWidthRight);
    detailsPanelRight.add(detailsCheckBox);
    detailsPanelRight.add(new HTML(GuiFactory.strings.displayDetails()));
    detailsPanel.add(detailsPanelLeft);
    detailsPanel.add(detailsPanelRight);   
    preferencesPanel.add(detailsPanel);
     
    // tree items open
    HorizontalPanel treesPanel = new HorizontalPanel(); 
    treesPanel.setHeight(panelHeight);
    HorizontalPanel treesPanelLeft = new HorizontalPanel();
    HorizontalPanel treesPanelRight = new HorizontalPanel();   
    treesPanelLeft.setWidth(panelWidthLeft);
    treesPanelLeft.add(new HTML("<b>" + GuiFactory.strings.treesOpen() + "</b>"));
    treesPanelRight.setWidth(panelWidthRight);
    treesPanelRight.add(treesCheckBox);
    treesPanelRight.add(new HTML(GuiFactory.strings.treesAlwaysOpen()));
    treesPanel.add(treesPanelLeft);
    treesPanel.add(treesPanelRight);   
    preferencesPanel.add(treesPanel);
         
    // request tab
    VerticalPanel requestPanel = new VerticalPanel(); 
    requestPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);

    // path to discoverer
    HorizontalPanel pathPanel = new HorizontalPanel();
    pathPanel.setHeight(panelHeight);
    HorizontalPanel pathPanelLeft = new HorizontalPanel();
    HorizontalPanel pathPanelRight = new HorizontalPanel();
    pathPanelLeft.setWidth(panelWidthLeft);
    pathPanelLeft.add(new HTML("<b>" + GuiFactory.strings.pathDiscover() + "</b>"));
    pathPanelRight.setWidth(panelWidthRight);
    pathPanelRight.add(pathToDiscovererTextBox);
    pathPanelRight.add(new HTML(GuiFactory.strings.pathToDiscoverer()));   
    pathPanel.add(pathPanelLeft);
    pathPanel.add(pathPanelRight);   
    requestPanel.add(pathPanel);
    
    // timeout
    HorizontalPanel timeoutPanel = new HorizontalPanel();
    timeoutPanel.setHeight(panelHeight);
    HorizontalPanel timeoutPanelLeft = new HorizontalPanel();
    HorizontalPanel timeoutPanelRight = new HorizontalPanel();
    timeoutPanelLeft.setWidth(panelWidthLeft);
    timeoutPanelLeft.add(new HTML("<b>" + GuiFactory.strings.timeout() + "</b>"));
    timeoutPanelRight.setWidth(panelWidthRight);
    timeoutPanelRight.add(timeoutSecondsTextBox);
    timeoutPanelRight.add(new HTML(GuiFactory.strings.timeoutSeconds()));   
    timeoutPanel.add(timeoutPanelLeft);
    timeoutPanel.add(timeoutPanelRight);   
    requestPanel.add(timeoutPanel);
    
    // code generation tab
    VerticalPanel codeGenerationPanel = new VerticalPanel(); 
    codeGenerationPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
    
    // naming depth
    HorizontalPanel namingDepthPanel = new HorizontalPanel();
    namingDepthPanel.setHeight(panelHeight);
    HorizontalPanel namingDepthPanelLeft = new HorizontalPanel();
    HorizontalPanel namingDepthPanelRight = new HorizontalPanel();
    namingDepthPanelLeft.setWidth(panelWidthLeft);
    namingDepthPanelLeft.add(new HTML("<b>" + GuiFactory.strings.namingDepth() + "</b>"));
    namingDepthPanelRight.setWidth(panelWidthRight);
    namingDepthPanelRight.add(namingDepthTextBox);
    namingDepthPanelRight.add(new HTML(GuiFactory.strings.namingDepthLevel()));   
    namingDepthPanel.add(namingDepthPanelLeft);
    namingDepthPanel.add(namingDepthPanelRight);   
    codeGenerationPanel.add(namingDepthPanel);
    
    // class default suffix
    HorizontalPanel classSuffixPanel = new HorizontalPanel();
    classSuffixPanel.setHeight(panelHeight);
    HorizontalPanel classSuffixPanelLeft = new HorizontalPanel();
    HorizontalPanel classSuffixPanelRight = new HorizontalPanel();
    classSuffixPanelLeft.setWidth(panelWidthLeft);
    classSuffixPanelLeft.add(new HTML("<b>" + GuiFactory.strings.classSuffix() + "</b>"));
    classSuffixPanelRight.setWidth(panelWidthRight);
    classSuffixPanelRight.add(classSuffixTextBox);
    classSuffixPanelRight.add(new HTML(GuiFactory.strings.classDefaultSuffix()));   
    classSuffixPanel.add(classSuffixPanelLeft);
    classSuffixPanel.add(classSuffixPanelRight);   
    codeGenerationPanel.add(classSuffixPanel);
    
    // source for class names
    HorizontalPanel classNamePanel = new HorizontalPanel();
    classNamePanel.setHeight(panelHeight);
    HorizontalPanel classNamePanelLeft = new HorizontalPanel();
    HorizontalPanel classNamePanelRight = new HorizontalPanel();
    classNamePanelLeft.setWidth(panelWidthLeft);
    classNamePanelLeft.add(new HTML("<b>" + GuiFactory.strings.className() + "</b>"));
    classNamePanelRight.setWidth(panelWidthRight);
    VerticalPanel radioPanel = new VerticalPanel();    
    radioPanel.add(useEndpointAsNameRadio);
    radioPanel.add(useParameterAsNameRadio);
    classNamePanelRight.add(radioPanel);       
    classNamePanel.add(classNamePanelLeft);
    classNamePanel.add(classNamePanelRight);   
    codeGenerationPanel.add(classNamePanel);
    
    // source for class names
    HorizontalPanel indentionPanel = new HorizontalPanel();
    indentionPanel.setHeight(panelHeight);
    HorizontalPanel indentionPanelLeft = new HorizontalPanel();
    HorizontalPanel indentionPanelRight = new HorizontalPanel();
    indentionPanelLeft.setWidth(panelWidthLeft);
    indentionPanelLeft.add(new HTML("<b>" + GuiFactory.strings.indentionStyle() + "</b>"));
    indentionPanelRight.setWidth(panelWidthRight);
    VerticalPanel indentionRadioPanel = new VerticalPanel();
    indentionRadioPanel.add(indentWithSpacesRadio);    
    indentMiniPanel.add(indentWidthTextBox);
    indentMiniPanel.add(new HTML(GuiFactory.strings.indentionWidth()));
    indentionRadioPanel.add(indentMiniPanel);
    indentionRadioPanel.add(indentWithTabsRadio);
    indentionPanelRight.add(indentionRadioPanel);       
    indentionPanel.add(indentionPanelLeft);
    indentionPanel.add(indentionPanelRight);   
    codeGenerationPanel.add(indentionPanel);
    
    // use separation character
    HorizontalPanel useSeparationCharacterPanel = new HorizontalPanel(); 
    useSeparationCharacterPanel.setHeight(panelHeight);
    HorizontalPanel useSeparationCharacterPanelLeft = new HorizontalPanel();
    HorizontalPanel useSeparationCharacterPanelRight = new HorizontalPanel();   
    useSeparationCharacterPanelLeft.setWidth(panelWidthLeft);
    useSeparationCharacterPanelLeft.add(new HTML("<b>" + GuiFactory.strings.sepChar() + "</b>"));
    useSeparationCharacterPanelRight.setWidth(panelWidthRight);
    VerticalPanel miniSepPanel = new VerticalPanel();    
    HorizontalPanel miniSepCheckPanel = new HorizontalPanel();
    miniSepPanel.add(miniSepCheckPanel);
    miniSepCheckPanel.add(useSeparationCharacterCheckBox);
    miniSepCheckPanel.add(new HTML(GuiFactory.strings.useSepChar()));    
    miniSepTextPanel.add(separationCharacterTextBox);
    miniSepTextPanel.add(new HTML(GuiFactory.strings.sepWithChar()));
    miniSepPanel.add(miniSepTextPanel);
    useSeparationCharacterPanelRight.add(miniSepPanel);    
    useSeparationCharacterPanel.add(useSeparationCharacterPanelLeft);
    useSeparationCharacterPanel.add(useSeparationCharacterPanelRight);   
    codeGenerationPanel.add(useSeparationCharacterPanel);
    
    tabPanel.add(generalPanel, "<a href=\"#\">" + GuiFactory.strings.generalTab() + "</a>", true);
    tabPanel.add(preferencesPanel, "<a href=\"#\">" + GuiFactory.strings.preferencesTab() + "</a>", true);
    tabPanel.add(requestPanel, "<a href=\"#\">" + GuiFactory.strings.requestTab() + "</a>", true);
    tabPanel.add(codeGenerationPanel, "<a href=\"#\">" + GuiFactory.strings.codeGenerationTab() + "</a>", true);
    tabPanel.selectTab(0);
       
    // ok button
    HorizontalPanel buttonPanel = new HorizontalPanel();
    Button okButton = new Button(GuiFactory.strings.ok());
    buttonPanel.add(okButton);
    okButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        // apply changes
        alwaysShowDetails = alwaysShowDetailsTemp;
        treeItemsAlwaysOpen = treeItemsAlwaysOpenTemp;
        useSeparationCharacter = useSeparationCharacterTemp;        
        RestCompilePanel.generateCode(CodeGenerator.language);
        GuiFactory.blockScreen(false);       
        dialogBox.hide();
      }
    });
     
    // cancel button
    Button closeButton = new Button(GuiFactory.strings.cancel());
    buttonPanel.add(closeButton);
    closeButton.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {    
        GuiFactory.blockScreen(false);
        dialogBox.hide();
      }
    });
     
    settingsPanel.add(new HTML("<br />"));
    settingsPanel.add(tabPanel);
    settingsPanel.add(new HTML("<br />"));
    settingsPanel.add(buttonPanel);
    settingsPanel.setCellHorizontalAlignment(buttonPanel, HasHorizontalAlignment.ALIGN_CENTER);
     
    dialogBox.setPopupPosition((int) Math.floor(Window.getClientWidth() / 4), (int) Math.floor(Window.getClientHeight() / 4));
    dialogBox.setWidget(settingsPanel);   
    GuiFactory.blockScreen(true);    
    dialogBox.show();   
  }
 
  private static void updateAndDisplayConfirmLink(String selectedLanguage, HTML confirmLink, HorizontalPanel confirmLangChange) {
    confirmLangChange.setVisible(true);
    confirmLink.setHTML("");
    if (selectedLanguage.equals(GuiFactory.strings.german())) {      
      confirmLink.setHTML(confirm_de);
    }
    else if (selectedLanguage.equals(GuiFactory.strings.english_US())) {
      confirmLink.setHTML(confirm_enUS);
    }
    else if (selectedLanguage.equals(GuiFactory.strings.catalan())) {
      confirmLink.setHTML(confirm_ca);
    }    
  }
} public class Uri {
  private String scheme = "", authority = "", path = "", query = "", fragment = "";
  
  /*
   *   foo://example.com:8042/over/there?name=ferret#nose
   *   \ /   \______________/\_________/ \_________/ \__/
   *    |           |             |           |        |
   *  scheme    authority       path        query   fragment
   * 
   */
  
  public Uri(String uriString) {   
    resolve(uriString);
  }
  
  private void resolve(String uriString) {
    try {
      // INPUT: http://whatever.com/some/path?some=query#someFragment
      // scheme
      int marker = uriString.indexOf("://");    
      if (marker > 0) {
        scheme = uriString.substring(0, marker);
        uriString = uriString.substring(marker + 3);
      }
      else {
        throw new InvalidUriException(GuiFactory.strings.invalidUri());   
      }
      
      // INPUT: whatever.com/some/path?some=query#someFragment
      // authority
      marker = uriString.indexOf("/");     
      if (marker > 0) {
        // whatever.com/...
        authority = uriString.substring(0, marker);      
      }
      // whatever.com 
      else {
        authority = uriString;
        return;
      }        
      uriString = uriString.substring(marker + 1);
      
      // INPUT: some/path?some=query#someFragment
      // path                  
      marker = uriString.indexOf("?");
      // some/path?...
      if (marker > 0) {  
        path = uriString.substring(0, marker);
        uriString = uriString.substring(marker);
      }
      else if (marker == -1) {
        // some/path#...
        marker = uriString.indexOf("#");
        if (marker > 0) {      
          path = uriString.substring(0, marker);
          uriString = uriString.substring(marker);
        }    
        else if (marker == -1) {
          // some/path/ or some/path
          path = uriString;        
          return;
        }
      }
      
      // INPUT: ?some=query#someFragment
      // query    
      marker = uriString.indexOf("#");    
      if (marker > 0) {
        // ?some=query#...
        query = uriString.substring(1, marker);
        uriString = uriString.substring(marker);
      }
      else if (marker == -1) {
        // ?some=query
        query = uriString.substring(1);
        return;
      }   
      
      // INPUT: #someFragment
      // fragment
      fragment = uriString.substring(1);
    } catch (InvalidUriException e) {      
    }
  }

  public String getScheme() {    
    return scheme;
  }

  public String getAuthority() {
    if (!authority.endsWith("/")) {
      return authority + "/";
    }
    return authority;
  }  
  
  public String getPath() {    
    return path;
  }
  
  public String getQuery() {
    if (query.startsWith("&")) return query.substring(1);
    else return query;
  }  
  
  public String getFragment() {    
    return fragment;
  }  
  
  public String[] getPathComponents() {    
    String[] pathComponents = this.getPath().split("/");
    if (pathComponents[0].length() == 0) {
      String[] newPathComponents = new String[pathComponents.length - 1];
      for (int i = 1; i < pathComponents.length; i++) {
        newPathComponents[i] = pathComponents[i];
      }
      pathComponents = newPathComponents;
    }
    return pathComponents;
  }
  
  public String[] getQueryParameters() {
    String[] queryParameters = this.getQuery().split("&");
    // this deals with the http://www.bla.com/bla?&var=param case ('?' followed immediately by '&')
    if (queryParameters[0].length() == 0) {
      String[] newQueryParameters = new String[queryParameters.length - 1];
      for (int i = 1; i < queryParameters.length; i++) {
        newQueryParameters[i] = queryParameters[i];
      }
      queryParameters = newQueryParameters;
    }
    for (int i = 0; i < queryParameters.length; i++) {      
      if (queryParameters[i].indexOf("=") > 0) {
        queryParameters[i] = queryParameters[i].substring(0, queryParameters[i].indexOf("="));
      }
      else {
        queryParameters[i] = "";
      }
    }
    return queryParameters;
  }
  
  public String[] getQueryValues() {
    String[] queryValues = this.getQuery().split("&");
    if (queryValues[0].length() == 0) {
      String[] newQueryValues = new String[queryValues.length - 1];
      for (int i = 1; i < queryValues.length; i++) {
        newQueryValues[i] = queryValues[i];
      }
      queryValues = newQueryValues;
    }
    for (int i = 0; i < queryValues.length; i++) {
      if (queryValues[i].indexOf("=") >= 0) {
        queryValues[i] = queryValues[i].substring(queryValues[i].indexOf("=") + 1);
      }
      else {        
        queryValues[i] = queryValues[i];
      }
    }
    return queryValues;
  }  
  
  public String toString() {
    String uriString = scheme + "://" + authority + "/";
    if (path.length() > 0) uriString += path;
    if (query.length() > 0) uriString += "?" + query;
    if (fragment.length() > 0) uriString += "#" + fragment;    
    return uriString;
  }

  public String getEndpoint() {
    String endpoint = scheme + "://" + authority;
    String[] pathCompontents = this.getPathComponents();
    for (int i = 0; i < pathCompontents.length - 1; i++) {
      endpoint += "/" + pathCompontents[i];
    }
    return endpoint;
  }

  public String getRequest() {
    String[] pathCompontents = this.getPathComponents();
    if (pathCompontents.length > 0) {
      return pathCompontents[pathCompontents.length - 1];
    }
    else {
      return "";
    }
  }  
}
 public class Analyzer {
  public static ApplicationNode application;
  private String requestString = "";
  private String referenceParamSuffix = "Param";  
  public static final String sampleValueHeader = " (Sample Value: ";
  public static final String sampleValueFooter = ")";
  public static final String templateParamOpenChar = "{";
  public static final String templateParamCloseChar = "}";
  public static final String templateParamRegExp = "^.*?(\\" + templateParamOpenChar + "(.+?)\\" + templateParamCloseChar + ")+.*?$";  
    
  /**
   * 
   */
  public Analyzer(String request) {
    this.requestString = request;
    return;
  }
  
  public String getRequestString() {
    return this.requestString; 
  } 

  public void setApplication(ApplicationNode applicationNode) {
    application = applicationNode;    
  }
    
  public ApplicationNode analyze() {
    Uri uri = new Uri(requestString.substring(requestString.indexOf(" ") + 1));
    
    String[] queryParameters = uri.getQueryParameters();
    String[] queryValues = uri.getQueryValues();
    String[] pathComponents = uri.getPathComponents();
        
    // <application>
    setApplication(new ApplicationNode(this));    
    
    // <resources>
    ResourcesNode resources = null;
    String base = uri.getScheme() + "://" + uri.getAuthority();
    if (application.getResources() == null) {
      resources = new ResourcesNode(base, application);
      application.addResources(resources);
    }
    else {
      resources = application.getResources();
      resources.updateBase(resources.getBase(), base);
    }    
    if ((pathComponents == null) || (pathComponents.length == 0)) return application; 
    
    // <resource> child of <resources>
    ResourceNode resource = new ResourceNode(pathComponents[0], resources, application);    
    if (!resources.addResource(resource)) {
      // share the already existing resource 
      resource = resources.getResourceByPath(pathComponents[0]);
    } 
    // check for potential necessary template parameters
    checkForTemplateParams(resource);
    
    // <resource> of other <resource>
    for (int i = 1; i < pathComponents.length; i++) {           
      ResourceNode newResource = new ResourceNode(pathComponents[i], resource, application);     
      if (!resource.addResource(newResource)) {      
        // share the already existing resource
        resource = resource.getResourceByPath(pathComponents[i]);        
      }
      else {
        // the new resource is not yet contained
        resource = newResource;
      }
      // check for potential necessary template parameters
      checkForTemplateParams(resource);
    }
    
    // <method>   
    String internalMethodId = "";
    for(int i = 0; i < queryParameters.length; i++) {
      internalMethodId += queryParameters[i];
    }
    ListBox httpMethodListBox = ReferenceManager.getHttpMethodListBox(requestString);
    String httpMethod = httpMethodListBox.getItemText(httpMethodListBox.getSelectedIndex());    
    MethodNode method = new MethodNode(httpMethod, resource, application);    
    if (!resource.addMethod(method)) {
      // share the already existing method, however reanalyze the request params      
      method = resource.getMethodByInternalId(internalMethodId); 
      method.getRequest().getAllParams().clear();
    }
    // make sure that even when recycling an old method the http method is correct
    method.updateName(method.getName(), httpMethod); 
    
    // <request>
    RequestNode request = new RequestNode(method, application);
    method.addRequest(request);
    
    // <param>
    for(int i = 0; i < queryParameters.length; i++) {
      String name = queryParameters[i];      
      String style = ParamItem.query;
      String[] typeEstimate = TypeEstimator.estimate(queryValues[i], queryParameters[i]);
      String type = typeEstimate[0];
      String estimateQuality = typeEstimate[1];
      boolean isRequired = false;
      boolean isRepeating = false; 
      String fixedValue = "";
      String path = "";
      String defaultValue = "";
      String value = queryValues[i];
      
      ParamNode param = new ParamNode(name, type, estimateQuality, style, isRequired, isRepeating, defaultValue, fixedValue, path, value, request, application);
      ApplicationNode.addPotentiallyToBeSharedParam(param);
      DocNode docNode;
      if (queryValues[i].length() > 0) {
        docNode = new DocNode("en", name + sampleValueHeader + queryValues[i] + sampleValueFooter, "", param);
      }
      else {
        docNode = new DocNode("en", name, "", param);
      }
      param.addDoc(docNode);
      request.addParam(param);      
    }
    if (application.getParamsToBeShared().size() > 0) {
      optimizeByOutsourcing();
    }
    return application;
  }

  /**
   * @return
   */
  private void optimizeByOutsourcing() {
    Vector paramsToBeShared = application.getParamsToBeShared();
    Vector usedIds = new Vector();
    for(Iterator i = paramsToBeShared.iterator(); i.hasNext(); /* empty */) {
      ParamNode param = (ParamNode) i.next();
      String id = param.getName() + referenceParamSuffix;
      if (usedIds.contains(id)) {
        int j = 1;
        while(usedIds.contains(id + j)) {
          // empty
        }
        id = id + j;
      }      
      usedIds.add(id);
      param.setId(id);
      application.addParam(param);
      replaceParamByReferenceParam(application.getResources(), param);
    }
  }

  /**
   * @param param
   */
  private void replaceParamByReferenceParam(GenericNode parent, ParamNode param) {
    Vector allResources = null;
    if (parent instanceof ResourcesNode) {
      allResources = ((ResourcesNode) parent).getAllResources();
    }
    else if (parent instanceof ResourceNode) {
      allResources = ((ResourceNode) parent).getAllResources();
    } 
    for (Iterator i = allResources.iterator(); i.hasNext(); /* empty */) {
      ResourceNode resource = (ResourceNode) i.next();
      if (resource.getAllMethods() != null) {
        Vector allMethods = resource.getAllMethods();
        for (Iterator j = allMethods.iterator(); j.hasNext(); /* empty */) {
          MethodNode method = (MethodNode) j.next();
          if (method.getRequest() != null) {
            RequestNode request = method.getRequest();
            if (request.getAllParams() != null) {
              Vector allParams = request.getAllParams();
              int paramIndex = 0;
              for(Iterator k = ((Vector) allParams.clone()).iterator(); k.hasNext(); /* empty */) {
                ParamNode p = (ParamNode) k.next();
                if (p.getName().equals(param.getName()) &&
                    p.getValue().equals(param.getValue())) {                  
                  request.removeParam(p);                  
                  ParamNode referenceParam = new ParamNode(param.getName(), request, application);
                  referenceParam.setHref("#" + param.getId());
                  request.insertParamAt(referenceParam, paramIndex);                  
                }
                paramIndex++;
              }
            }  
          }        
        }
      }
      replaceParamByReferenceParam(resource, param);
    }
  }
  
  /**
   * @param resource
   */
  private void checkForTemplateParams(ResourceNode resource) {
    // check if we have a template path like /shop/{cartId}/      
    if (resource.getPath().matches(templateParamRegExp)) {     
      String path = resource.getPath();        
      int indexOfOpen = path.indexOf(templateParamOpenChar);
      int indexOfClose = path.indexOf(templateParamCloseChar);        
      while(indexOfOpen >= 0 &&
          indexOfClose > 0 &&
          indexOfOpen < indexOfClose) {          
        String templateParamName = path.substring(indexOfOpen + 1, indexOfClose);          
        ParamNode templateParam = new ParamNode(
            templateParamName,
            TypeEstimator.typeString,            
            ParamItem.template,
            resource,
            application);
        resource.addParam(templateParam);
        path = path.substring(indexOfClose + 1);
        indexOfOpen = path.indexOf(templateParamOpenChar);
        indexOfClose = path.indexOf(templateParamCloseChar);
      }        
    }    
  }

  /**
   * @param request
   */
  public void setRequestString(String request) {
    requestString = request;    
  }
}
 public class ApplicationNode extends GenericNode {
  // each new <application> node shares the already existing <resources> node
  private static ResourcesNode resources;
  // each new <application> node shares the already existing <grammars> node
  public static GrammarsNode grammars;
  // each new <application> node shares the already existing @extNs attributes
  private static Vector allNamespaces = new Vector();
  // each new <application> node shares the already existing <fault> nodes
  private Vector allFaults = new Vector();
  // each new <application> node shares the already existing <method> nodes
  private static Vector allMethods = new Vector();
  // each new <application> node shares the already existing <method> nodes
  private static Vector allRepresentations = new Vector();
  // each new <application> node shares the already existing <param> nodes
  private static Vector allParams = new Vector();
  // each new <application> node shares the already existing <resource_type> nodes
  private static Vector allResourceTypes = new Vector();
  private static Vector paramsPotentiallyToBeShared = new Vector();
  private static Vector paramsToBeShared = new Vector();
  private Analyzer analyzer;
    
  public ApplicationNode(Analyzer requestAnalyzer) {
    analyzer = requestAnalyzer;
    return;
  }  
  
  public Vector getParamsToBeShared() {
    return paramsToBeShared;
  }
  
  public Analyzer getAnalyzer() {
    return analyzer;
  }
  
  public GrammarsNode getGrammars() {    
    return grammars;
  }
  
  public ResourcesNode getResources() {
    return resources;     
  }
  
  public void addGrammars(GrammarsNode grammarsNode) {
    grammars = grammarsNode;
  }
  
  public void addResources(ResourcesNode resourcesNode) {    
    resources = resourcesNode;    
  }
  
  public void addNamespace(NamespaceAttribute namespace) {
    if (!namespaceAlreadyContained(namespace)) {
      allNamespaces.add(namespace);
    }
  }
  
  public static void addPotentiallyToBeSharedParam(ParamNode param) {
    for(Iterator i = paramsPotentiallyToBeShared.iterator(); i.hasNext(); /* empty */) {
      ParamNode p = (ParamNode) i.next();
      if (p.getName().equals(param.getName()) &&
          p.getValue().equals(param.getValue())) {
        addToBeSharedParam(param);
      }      
    }
    paramsPotentiallyToBeShared.add(param);
  }
  
  /**
   * @param param
   */
  private static void addToBeSharedParam(ParamNode param) {
    for(Iterator i = paramsToBeShared.iterator(); i.hasNext(); /* empty */) {
      ParamNode p = (ParamNode) i.next();
      if (p.getName().equals(param.getName()) &&
          p.getValue().equals(param.getValue())) {
        return;
      }      
    }
    paramsToBeShared.add(param);    
  }

  private boolean namespaceAlreadyContained(NamespaceAttribute namespaceToCheck) {
    Iterator namespaceIterator = allNamespaces.iterator();
    while(namespaceIterator.hasNext()) {
      NamespaceAttribute namespace = (NamespaceAttribute) namespaceIterator.next();
      if (namespace.getValue().equals(namespaceToCheck.getValue())) {
        return true;
      }
    }
    return false;
  }
  
  public void removeNamespace(String namespaceValue) {
    Iterator allNamespacesIterator = allNamespaces.iterator();
    while(allNamespacesIterator.hasNext()) {
      NamespaceAttribute namespace = (NamespaceAttribute) allNamespacesIterator.next();
      if (namespace.getValue().equals(namespaceValue)) {
        allNamespaces.remove(namespace);
        break;
      }
    }
  }
  
  public Vector getAllNamespaces() {
    return allNamespaces;
  }

  public void updateNamespace(String oldNamespace, String newNamespace) {
    Iterator allNamespacesIterator = allNamespaces.iterator();
    while(allNamespacesIterator.hasNext()) {
      NamespaceAttribute namespace = (NamespaceAttribute) allNamespacesIterator.next();
      if (namespace.getValue().equals(oldNamespace)) {
        namespace.setValue(newNamespace);        
        break;
      }
    }
  }
  
  public void addParam(ParamNode param) {    
    if (!allParams.contains(param)) {
      allParams.add(param);
    }
  }
  
  public Vector getAllParams() {    
    return allParams;
  }

  public void removeParam(ParamNode param) {
    if (allParams.contains(param)) {
      allParams.remove(param);
    }    
  }
  
  public void removeFault(FaultNode fault) {
    if (allFaults.contains(fault)) {
      allFaults.remove(fault);
    }    
  }
  
  public void addFault(FaultNode fault) {
    if (!allFaults.contains(fault)) {
      allFaults.add(fault);
    }
  }

  public Vector getAllFaults() {    
    return allFaults;
  }
  
  public void addRepresentation(RepresentationNode representation) {    
    if (!allRepresentations.contains(representation)) {
      allRepresentations.add(representation);
    }
   }
  
  public Vector getAllRepresentations() {    
    return allRepresentations;
  }

  public void removeRepresentation(RepresentationNode representation) {
    if (allRepresentations.contains(representation)) {
      allRepresentations.remove(representation);
    }    
  }

  /**
   * Resets the current application node
   */
  public void reset() {    
    if (paramsPotentiallyToBeShared != null) {
      paramsPotentiallyToBeShared.clear();
    }
    if (paramsToBeShared != null) {
      paramsToBeShared.clear();
    }    
    if (allResourceTypes != null) {
      allResourceTypes.clear();
    }
    if (allNamespaces != null) {
      allNamespaces.clear();
    }
    if (allMethods != null) {
      allMethods.clear();
    }
    if (allParams != null) {
      allParams.clear();
    }    
    if (allFaults != null) {
      allFaults.clear();
    }
    if (allRepresentations != null) {
      allRepresentations.clear();
    }
    if (resources != null) {
      resources.getAllResources().clear();
      resources.updateBase(resources.getBase(), "");
    }
    if (grammars != null) {
      grammars.getAllIncludes().clear();
    }
  }

  public Vector getAllMethods() {
    return allMethods;
  }
  
  public boolean addMethod(MethodNode method) {
    if (!alreadyContainesMethod(allMethods, method.getInternalMethodId())) {
      allMethods.add(method);      
      return true;
    }
    else {
      return false;
    }
  }
  
  public void directlyAddMethod(MethodNode method) {    
    allMethods.add(method);    
  }

  public void removeMethod(MethodNode method) {
    if (allMethods.contains(method)) {
      allMethods.remove(method);
    }    
  }
  
  public static boolean alreadyContainesMethod(Vector allMethods, String internalMethodId) {
    if (internalMethodId == null) {
      return false;
    }
    Iterator allMethodsIterator = allMethods.iterator();
    while (allMethodsIterator.hasNext()) {
      MethodNode method = (MethodNode) allMethodsIterator.next();
      if (method.getInternalMethodId() == null) {
        continue;
      }
      if (method.getInternalMethodId().equals(internalMethodId)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @return
   */
  public Vector getAllResourceTypes() {    
    return allResourceTypes;
  }
  
  public void addResourceType(ResourceTypeNode resourceType) {    
    allResourceTypes.add(resourceType);
  }
  
  public void removeResourceType(ResourceTypeNode resourceType) {
    if (allResourceTypes.contains(resourceType)) {
      allResourceTypes.remove(resourceType);
    }
  }

  /**
   * 
   */
  public void removeResources() {
    resources = null;    
  }

  /**
   * 
   */
  public void removeGrammars() {
    grammars = null;    
  }
}
 public class FaultNode extends FaultRepSuperNode {
  
  public FaultNode(String faultMediaType, String faultElement, String faultProfile, String faultStatus, GenericNode parent, ApplicationNode application) {
    super(parent, application);
    super.mediaType = faultMediaType;
    super.element = faultElement;
    super.profile = faultProfile;
    super.status = faultStatus;    
  }
  
  public FaultNode(String faultStatus, GenericNode parent, ApplicationNode application) {
    super(parent, application);
    mediaType = "";
    element = "";
    profile = "";
    status = faultStatus;    
  }
  
  public FaultNode(String id, boolean isReferenced, GenericNode parent, ApplicationNode application) {
    super(parent, application, id);
    mediaType = "";
    element = "";
    profile = "";    
  }
} public class MethodNode extends GenericNode {
  private Vector allParams = new Vector();  
  private String name;
  private String id;
  private String href;
  private RequestNode request;
  private ResponseNode response; 
  
  public MethodNode(String methodName, GenericNode node, ApplicationNode application) {
    name = methodName;    
    super.parent = node;
    super.application = application;
  }
  
  public MethodNode(String methodId, boolean isReferenced, GenericNode node, ApplicationNode application) {
    name = null;
    id = null;
    href = "#" + methodId;    
    super.parent = node;
    super.application = application;
  }
  
  public String getName() {
    return name;
  } 
  
  public String getInternalMethodId() {
    String internalMethodId = "";
    if (this.getRequest() != null && this.getRequest().getAllParams() != null) {
      Vector allParams = this.getRequest().getAllParams();
      for (Iterator allParamsIterator = allParams.iterator(); allParamsIterator.hasNext(); /* empty */) {
        ParamNode param = (ParamNode) allParamsIterator.next();
        internalMethodId += param.getName();
      }
    }
    return internalMethodId;
  }
  
  public String getId() {
    return id;
  }  
  
  public void updateId(String oldId, String newId) {
    if (oldId.equals(getId())) {
      id = newId;      
    }
  }
  
  public void updateName(String oldName, String newName) {
    if (getName().equals(oldName)) {
      name = newName;
    }
  }

  public void addParam(ParamNode param) {    
    allParams.add(param);
  }
  
  public Vector getAllParams() {    
    return allParams;
  }

  public void addRequest(RequestNode requestNode) {
    request = requestNode;
  }
  
  public RequestNode getRequest() {
    return request;
  }

  public void addResponse(ResponseNode responseNode) {
    response = responseNode;
  }
  
  public ResponseNode getResponse() {
    return response;
  }

  /**
   * @return
   */
  public String getHref() {    
    return href;
  }

  /**
   * @param methodId
   */
  public void setId(String methodId) {
    id = methodId;    
  }

  /**
   * @param requestNode
   */
  public void removeRequest(RequestNode requestNode) {
    request = null;    
  }
  
  /**
   * @param responseNode
   */
  public void removeResponse(ResponseNode responseNode) {
    response = null;    
  }
}
 public class ParamNode extends GenericNode {
  private String name;  
  private String type;
  private String estimateQuality; 
  private String style;
  private String id;
  private String href;
  private boolean isRequired;
  private boolean isRepeating;
  private String defaultValue;
  private String fixedValue;
  private String value;
  private String path;
  private Vector options = new Vector();
  private Vector allLinks = new Vector();
  
  public ParamNode(String paramName, String paramType, String typeEstimateQuality, String paramStyle, boolean paramIsRequired, boolean paramIsRepeating, String paramDefaultValue, String paramFixedValue, String paramPath, String paramValue, GenericNode parent, ApplicationNode application) {
    name = paramName;    
    type = paramType;
    estimateQuality = typeEstimateQuality;
    style = paramStyle;
    href = null;
    isRequired = paramIsRequired;
    isRepeating = paramIsRepeating;
    defaultValue = paramDefaultValue;
    fixedValue = paramFixedValue;   
    path = paramPath;
    value = paramValue;
    super.parent = parent;
    super.application = application;
  }

  public ParamNode(String paramName, GenericNode parent, ApplicationNode application) {
    name = paramName;    
    type = TypeEstimator.typeString;
    estimateQuality = TypeEstimator.manual;
    style = ParamItem.query;
    isRequired = false;
    isRepeating = false;
    href = null;
    defaultValue = "";
    fixedValue = "";
    path = "";
    value = GuiFactory.strings.paramValue();
    super.parent = parent;
    super.application = application;
  }
  
  public ParamNode(String paramId, boolean isReferenced, GenericNode parent, ApplicationNode application) {
    id = null;    
    href = "#" + paramId;
    type = "";
    estimateQuality = "";
    style = "";
    isRequired = false;
    isRepeating = false;
    defaultValue = "";
    fixedValue = "";
    path = "";
    value = "";
    super.parent = parent;
    super.application = application;
  }

  /**
   * This is a template parameter constructor for resources with a path like .../shop/{cartId}/...
   * @param templateParamName
   * @param typeString
   * @param template
   * @param resource
   * @param application
   */
  public ParamNode(String templateParamName, String typeString, String template, ResourceNode resource, ApplicationNode application) {
    name = templateParamName;
    type = typeString;
    style = template;
    estimateQuality = "";
    defaultValue = "";
    fixedValue = "";
    path = "";
    super.parent = resource;
    super.application = application;
  }

  public String getName() {
    return name;    
  }
  
  public String getId() {
    return id;
  }
 
  public String getPath() {
    return path;    
  }
  
  public String getValue() {
    return value;
  }
  
  public String getType() {
    return type;
  }
  
  public String getEstimateQuality() {
    return estimateQuality;
  }
  
  public void setEstimateQuality(String quality) {
    estimateQuality = quality;
  }
  
  public String getStyle() {
    return style;
  }
  
  public boolean getIsRequired() {
    return isRequired;
  }
  
  public String getDefaultValue() {
    return defaultValue;
  }
  
  public String getFixedValue() {
    return fixedValue;
  }
  
  public boolean getIsRepeating() {
    return isRepeating;
  }

  public void updateName(String oldName, String newName) {
    if (oldName.equals(getName())) {
      name = newName;
    }
  }
 
  public void updateId(String oldId, String newId) {
    if (oldId.equals(getId())) {
      id = newId;      
    }
  }
  
  public void updateType(String oldType, String newType) {
    if (oldType.equals(getType())) {
      type = newType;
      estimateQuality = TypeEstimator.manual;
    }
  }
  
  public void updatePath(String oldPath, String newPath) {
    if (oldPath.equals(getPath())) {
      path = newPath;
      estimateQuality = TypeEstimator.manual;
    }
  }
  
  public void updateDefaultValue(String oldDefaultValue, String newDefaultValue) {
    if (oldDefaultValue.equals(getDefaultValue())) {
      defaultValue = newDefaultValue;
    }
  }
  
  public void updateFixedValue(String oldFixedValue, String newFixedValue) {
    if (oldFixedValue.equals(getFixedValue())) {
      fixedValue = newFixedValue;
    }
  }
  
  public void updateStyle(String oldStyle, String newStyle) {
    if (oldStyle.equals(getStyle())) {
      style = newStyle;
    }
  }
  
  public void updateIsRequired(boolean oldIsRequired, boolean newIsRequired) {
    if (oldIsRequired == getIsRequired()) {
      isRequired = newIsRequired;
    }
  }
  
  public void updateIsRepeating(boolean oldIsRepeating, boolean newIsRepeating) {
    if (oldIsRepeating == getIsRepeating()) {
      isRepeating = newIsRepeating;
    }
  }

  public Vector getOptions() {    
    return options ;
  }

  public void setOptions(Vector optionValues) {
    options = optionValues;   
  }

  public void addOption(String option) {
    if (!options.contains(option)) {
      options.add(option);
    }
  }
  
  /**
   * @return
   */
  public Vector getAllLinks() {    
    return allLinks;
  }

  /**
   * @return
   */
  public String getHref() {
    return href;
  }

  /**
   * @param nodeValue
   */
  public void setId(String newId) {
    id = newId;    
  }

  /**
   * @param string
   */
  public void setHref(String href) {
    this.href = href;    
  }  
}
 public class RepresentationNode extends FaultRepSuperNode {
  
  public RepresentationNode(String representationMediaType, String representationElement, String representationProfile, String representationStatus, GenericNode parent, ApplicationNode application) {
    super(parent, application);
    super.mediaType = representationMediaType;
    super.element = representationElement;
    super.profile = representationProfile;
    super.status = representationStatus;    
  }
  
  public RepresentationNode(String representationElement, String mediaType, GenericNode parentNode, ApplicationNode application) {
    super(parentNode, application);
    super.mediaType = mediaType;
    super.element = representationElement;
    super.profile = "";   
    super.status = "";
  }

  public RepresentationNode(String id, boolean isReferenced, GenericNode parentNode, ApplicationNode application) {
    super(parentNode, application, id);
    super.mediaType = "";
    super.element = "";
    super.profile = "";        
  } 
} public class RequestNode extends GenericNode {
  private Vector allParams = new Vector();
  private Vector allRepresentations = new Vector();
  
  public RequestNode(MethodNode method, ApplicationNode application) {
    super.parent = method;
    super.application = application;
  }

  public void addParam(ParamNode param) {    
    if (!allParams.contains(param)) {
      allParams.add(param);
    }
  }
  
  public void insertParamAt(ParamNode param, int index) {
    allParams.insertElementAt(param, index);
  }
  
  public Vector getAllParams() {    
    return allParams;
  }

  public void removeParam(ParamNode param) {
    if (allParams.contains(param)) {
      allParams.remove(param);
    }    
  }

  public void addRepresentation(RepresentationNode representation) {    
    if (!allRepresentations.contains(representation)) {
      allRepresentations.add(representation);
    }
   }
  
  public Vector getAllRepresentations() {    
    return allRepresentations;
  }

  public void removeRepresentation(RepresentationNode representation) {
    if (allRepresentations.contains(representation)) {
      allRepresentations.remove(representation);
    }    
  }
}
 public class ResourceNode extends GenericNode {
  private Vector allParams = new Vector();
  private Vector allMethods = new Vector();
  // resource nodes can contain resources
  private Vector allResources = new Vector();
  private String path;
  private String id;
  private String href;
  private String absolutePath = "";
    
  public ResourceNode(String resourcePath, GenericNode parentNode, ApplicationNode application) {
    path = resourcePath;
    super.parent = parentNode;
    super.application = application;
    
    // here we need to take care whether the parent node is a <resource> or <resources> element
    ResourceNode copyOfMyself = this;
    while (copyOfMyself.getParent() instanceof ResourceNode) {      
      absolutePath = ((ResourceNode) copyOfMyself.getParent()).getPath() + "/" + absolutePath;
      copyOfMyself = (ResourceNode) copyOfMyself.getParent();
    }    
    if (copyOfMyself.getParent() instanceof ResourcesNode) {      
      absolutePath =  ((ResourcesNode) copyOfMyself.getParent()).getBase() + absolutePath;
    }
  }
  
  /**
   * @param nodeValue
   * @param isReferenced
   * @param node
   * @param application
   */
  public ResourceNode(String resourceId, boolean isReferenced, GenericNode parentNode, ApplicationNode application) {
    id = null;
    href = "#" + resourceId;
    super.parent = parentNode;
    super.application = application;
  }

  public String getPath() {
    return path;
  }
  
  public void addParam(ParamNode param) {
    Iterator allParamsIterator = allParams.iterator();
    while(allParamsIterator.hasNext()) {
      ParamNode parameter = (ParamNode) allParamsIterator.next();
      if (param.getName().equals(parameter.getName())) {
        // the param to be inserted is already contained
        return;
      }
    }    
    allParams.add(param);
  }
  
  public void updatePath(String oldPath, String newPath) {
    if (getPath().equals(oldPath)) {
      path = newPath;
    }
  }
  
  public Vector getAllParams() {    
    return allParams;
  }
  
  public void removeParam(ParamNode param) {
    if (allParams.contains(param)) {
      allParams.remove(param);
    }    
  }

  public Vector getAllMethods() {
    return allMethods;
  }
  
  public boolean addMethod(MethodNode method) {    
    if (!ApplicationNode.alreadyContainesMethod(allMethods, method.getInternalMethodId())) {
      allMethods.add(method);
      return true;
    }
    else {
      return false;
    }
  }

  public void directlyAddMethod(MethodNode method) {    
    allMethods.add(method);    
  }
  
  public void removeMethod(MethodNode method) {    
    if (allMethods.contains(method)) {
      allMethods.remove(method);
    }    
  }
  
  public Vector getAllResources() {
    return allResources;
  }
  
  public boolean alreadyContainesResource(String path) {       
    Iterator allResourcesIterator = allResources.iterator();
    while (allResourcesIterator.hasNext()) {
      ResourceNode resource = (ResourceNode) allResourcesIterator.next();      
      if (resource.getPath().equals(path)) {
        return true;
      }
    }    
    return false;
  }
  
  public boolean addResource(ResourceNode resource) {    
    if (!alreadyContainesResource(resource.getPath())) {      
      allResources.add(resource);      
      return true;
    }
    else {
      return false;
    }
  }
  
  public ResourceNode getResourceByPath(String path) {
    Vector allResources = getAllResources();
    Iterator allResourcesIterator = allResources.iterator();
    while (allResourcesIterator.hasNext()) {
      ResourceNode resource = (ResourceNode) allResourcesIterator.next();      
      if (resource.getPath().equals(path)) {
        return resource;
      }
    }    
    return null;
  }
  
  public void removeResource(ResourceNode resource) {
    if (allResources.contains(resource)) {
      allResources.remove(resource);
    }
  }
  
  public void updateResources(ResourceNode oldResource, ResourceNode newResource) {
    if (allResources.contains(oldResource)) {
      allResources.remove(oldResource);
      allResources.add(newResource);
    }    
  }

  public String getAbsolutePath() {
    return absolutePath;    
  }  

  /**
   * @return
   */
  public String getId() {
    return id;
  }

  /**
   * @return
   */
  public String getHref() {    
    return href;
  }

  /**
   * @param newId
   */
  public void setId(String newId) {
    id = newId;    
  }

  public MethodNode getMethodByInternalId(String internalMethodId) {
    Iterator allMethodsIterator = allMethods.iterator();
    while (allMethodsIterator.hasNext()) {
      MethodNode method = (MethodNode) allMethodsIterator.next();
      if (method.getInternalMethodId().equals(internalMethodId)) {
        return method;
      }
    }
    return null;
  }
}
 public class ResourceTypeNode extends GenericNode {
  private String id;
  private String href;
  private Vector allParams = new Vector();
  private Vector allMethods = new Vector();
  
  /**
   * @param string
   * @param parentNode   
   */
  public ResourceTypeNode(String resourceTypeId, ApplicationNode parentNode) {
    id = resourceTypeId;
    super.parent = parentNode;    
    super.application = parentNode;
  }

  public String getId() {
    return id;
  }
  
  public String getHref() {
    return href;
  }
      
  public boolean addMethod(MethodNode method) {
    if (!ApplicationNode.alreadyContainesMethod(allMethods, method.getInternalMethodId())) {
      allMethods.add(method);
      return true;
    }
    else {
      return false;
    }
  }

  public void directlyAddMethod(MethodNode method) {    
    allMethods.add(method);    
  }
  
  public void removeMethod(MethodNode method) {    
    if (allMethods.contains(method)) {
      allMethods.remove(method);
    }    
  }

  /**
   * @return
   */
  public Vector getAllMethods() {
    return allMethods;
  }

  public void addParam(ParamNode param) {    
    if (!allParams.contains(param)) {
      allParams.add(param);
    }
  }
  
  public Vector getAllParams() {    
    return allParams;
  }

  public void removeParam(ParamNode param) {
    if (allParams.contains(param)) {
      allParams.remove(param);
    }    
  }

  public void updateId(String oldId, String newId) {
    if (oldId.equals(id)) {
      id = newId;
    }
  }
} public class ResourcesNode extends GenericNode {
  // each new <resources> node shares the already existing @base attribute
  private static String base;
  // each new <resources> node shares the already existing <resource> nodes
  private static Vector allResources = new Vector();
    
  public ResourcesNode(String resourcesBase, ApplicationNode application) {
    if (!resourcesBase.endsWith("/")) {
      resourcesBase += "/";
    }
    base = resourcesBase;
    allResources.clear();
    super.parent = application;
    super.application = application;
  }
  
  public String getBase() {
    return base;    
  }
   
  public Vector getAllResources() {
    return allResources;
  }
  
  public boolean alreadyContained(String path) {    
    Iterator allResourcesIterator = allResources.iterator();
    while (allResourcesIterator.hasNext()) {
      ResourceNode resource = (ResourceNode) allResourcesIterator.next();      
      if (resource.getPath().equals(path)) {
        return true;
      }
    }    
    return false;
  }
  
  public ResourceNode getResourceByPath(String path) {
    Iterator allResourcesIterator = allResources.iterator();
    while (allResourcesIterator.hasNext()) {
      ResourceNode resource = (ResourceNode) allResourcesIterator.next();      
      if (resource.getPath().equals(path)) {
        return resource;
      }
    }    
    return null;
  }
  
  public boolean addResource(ResourceNode resource) {    
    if (!alreadyContained(resource.getPath())) {      
      allResources.add(resource);      
      return true;
    }
    else {
      return false;
    }
  }
  
  public void removeResource(ResourceNode resource) {
    if (allResources.contains(resource)) {
      allResources.remove(resource);
    }
  }
  
  public void updateBase(String oldBase, String newBase) {
    if (oldBase.equals(base)) {
      base = newBase;
    }
  }
    
  public void updateResources(ResourceNode oldResource, ResourceNode newResource) {
    if (allResources.contains(oldResource)) {
      allResources.remove(oldResource);
      allResources.add(newResource);
    }    
  }  
}
 public class ResponseNode extends GenericNode {
  private Vector allParams = new Vector();
  private Vector allRepresentations = new Vector();
  private Vector allFaults = new Vector();  

  public ResponseNode(MethodNode method, ApplicationNode application) {   
    super.parent = method;
    super.application = application;
  }
  
  public void addParam(ParamNode param) {    
   if (!allParams.contains(param)) {
     allParams.add(param);
   }
  }
    
  public Vector getAllParams() {    
    return allParams;
  }
  
  public void removeParam(ParamNode param) {
    if (allParams.contains(param)) {
      allParams.remove(param);
    }    
  }

  public void addRepresentation(RepresentationNode representation) {    
    if (!allRepresentations.contains(representation)) {
      allRepresentations.add(representation);
    }
   }
  
  public Vector getAllRepresentations() {    
    return allRepresentations;
  }

  public void removeRepresentation(RepresentationNode representation) {
    if (allRepresentations.contains(representation)) {
      allRepresentations.remove(representation);
    }    
  }

  public void removeFault(FaultNode fault) {
    if (allFaults.contains(fault)) {
      allFaults.remove(fault);
    }    
  }
  
  public void addFault(FaultNode fault) {
    if (!allFaults.contains(fault)) {
      allFaults.add(fault);
    }
  }

  public Vector getAllFaults() {    
    return allFaults;
  }
}

import java.util.Iterator;
import java.util.Vector;
import com.google.code.apis.rest.client.GUI.RestCompilePanel;
import com.google.code.apis.rest.client.GUI.SettingsDialog;
import com.google.code.apis.rest.client.Util.Uri;
import com.google.code.apis.rest.client.Wadl.Analyzer;
import com.google.code.apis.rest.client.Wadl.ApplicationNode;
import com.google.code.apis.rest.client.Wadl.FaultNode;
import com.google.code.apis.rest.client.Wadl.MethodNode;
import com.google.code.apis.rest.client.Wadl.ParamNode;
import com.google.code.apis.rest.client.Wadl.RepresentationNode;
import com.google.code.apis.rest.client.Wadl.RequestNode;
import com.google.code.apis.rest.client.Wadl.ResourceNode;
import com.google.code.apis.rest.client.Wadl.ResourceTypeNode;
import com.google.code.apis.rest.client.Wadl.ResourcesNode;
import com.google.code.apis.rest.client.Wadl.ResponseNode;
/**
 * 
 */
package com.google.code.apis.rest.client.CodeGeneration;



/**
 * @author tsteiner
 *
 */
public class CodeGenerator {
  // available languages
  public static final String php5 = "PHP 5";
  public static final String java = "Java";
  public static final String python = "Python";
  public static final String ruby = "Ruby";
  public static final String csharp = "C#";    
  public static final String dogfood_php5 = "Dog Food PHP 5";
  
  private Vector faults = new Vector();  
  public static Vector usedClassNames = new Vector();  
  public static String language = "";
  private ApplicationNode application;
  private Object generator;
  private Vector variables = new Vector();
  
  /**
   * constructor
   * 
   * @param applicationNode
   */
  public CodeGenerator(ApplicationNode applicationNode) {   
    application = applicationNode;
  }
  
  public String generate(String lang) {
    usedClassNames.clear();
    language = lang;    
    
    if (language.equals(php5)) {
      PHP5Generator phpGenerator = new PHP5Generator();
      generator = phpGenerator;
      runThroughSyntaxTree();
      return decodeEntities(phpGenerator.generate(faults));
    }    
    else if (language.equals(ruby)) {
      RubyGenerator rubyGenerator = new RubyGenerator();
      generator = rubyGenerator;
      runThroughSyntaxTree();
      return decodeEntities(rubyGenerator.generate(faults));
    }
    else if (language.equals(python)) {
      PythonGenerator pythonGenerator = new PythonGenerator();
      generator = pythonGenerator;
      runThroughSyntaxTree();
      return decodeEntities(pythonGenerator.generate(faults));
    }
    else if (language.equals(java)) {
      JavaGenerator javaGenerator = new JavaGenerator(getPackageName());
      generator = javaGenerator;
      runThroughSyntaxTree();
      return decodeEntities(javaGenerator.generate(faults));
    }
    else if (language.equals(dogfood_php5)) {
      DogFoodPHP5Generator dogFoodPhpGenerator = new DogFoodPHP5Generator();
      generator = dogFoodPhpGenerator;
      runThroughSyntaxTree();      
      return decodeEntities(dogFoodPhpGenerator.generate(faults));      
    }    
    return null;
  }
  
  private void createRequestClass(RequestMessager requestMessager) {
    if (language.equals(php5)) {
      ((PHP5Generator) generator).createRequestClass(requestMessager);
    }    
    else if (language.equals(ruby)) {
      ((RubyGenerator) generator).createRequestClass(requestMessager);
    }
    else if (language.equals(python)) {
      ((PythonGenerator) generator).createRequestClass(requestMessager);
    }
    else if (language.equals(java)) {
      ((JavaGenerator) generator).createRequestClass(requestMessager);
    }
    else if (language.equals(dogfood_php5)) {
      ((DogFoodPHP5Generator) generator).createRequestClass(requestMessager);
    }
  }
  
  private String decodeEntities(String code) {
    code = code.replaceAll("&lt;", "<");
    code = code.replaceAll("&gt;", ">");
    code = code.replaceAll("&nbsp;", " ");
    code = code.replaceAll("&apos;", "'");
    code = code.replaceAll("&quot;", "\"");
    code = code.replaceAll("&#123;", "{");
    code = code.replaceAll("&#125;", "}");
    if (SettingsDialog.indentWithSpaces) {