package model;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.PatternSyntaxException;
import javax.swing.JOptionPane;
import misc.ResultTreeNode;
import application.Application;
public class Model {
// Models
private InputText inputText;
private RegEx regEx;
private PropertyChangeSupport changesSupport = new PropertyChangeSupport(this);
private int caretPosition = 0;
/**
* Create models
*/
public Model(int undoLevel) {
super();
inputText = new InputText();
regEx = new RegEx(undoLevel);
}
//--------------------------------------------------------------------------------------
// RegEx methods
/**
* setRegEx is called by the view to set the new value of the regular expression
* setRegEx will set the new value to the RegEx Model and fire a propertychange on the validity
* @param regex
*/
public void setRegEx(String regex) {
// Fire the new state (valid or not)
PatternSyntaxException oldValidity = regEx.checkValidity();
changesSupport.firePropertyChange("regEx", regEx.getRegularExpression(), regEx.setRegularExpression(regex));
PatternSyntaxException validity = regEx.checkValidity();
changesSupport.firePropertyChange("valid", oldValidity, validity);
if (validity == null)
updateRegExTree();
}
public String getRegularExpression() {
return regEx.getRegularExpression();
}
/**
* called by CreationPanel when the user wants to add an item
* Futur improvement will include option to add the item where the cursor is
* in the regExTextPanel
* @param newItem
*/
private boolean flagCaretEditing = false;
public void addRegExItem(String newItem) {
flagCaretEditing = true;
// if the selected item to add is the grouping structure
int oldCaretPosition = this.caretPosition;
if (newItem.equals("()")) {
String beginning = regEx.getRegularExpression().substring(0, regEx.getIndexStart());
String between = regEx.getRegularExpression().substring(regEx.getIndexStart(), regEx.getIndexEnd());
String ending = regEx.getRegularExpression().substring(regEx.getIndexEnd());
this.setRegEx(beginning+"("+between+")"+ending);
}
else
{
if(this.caretPosition > regEx.getRegularExpression().length())
{
if(regEx.getRegularExpression().length()>0)
this.caretPosition = regEx.getRegularExpression().length();
else
this.caretPosition =0;
}
String beginning = regEx.getRegularExpression().substring(0, this.caretPosition);
String ending = regEx.getRegularExpression().substring(this.caretPosition,regEx.getRegularExpression().length());
this.setRegEx(beginning + newItem + ending);
}
this.caretPosition += newItem.length();
flagCaretEditing = false;
changesSupport.firePropertyChange("caretPosition", oldCaretPosition, this.caretPosition);
}
/**
* applyRegEx is used to apply the regex on the input text
* then fires the resultTree to the resultPanel and inputText
*/
public void applyRegEx() {
if (!inputText.getText().equalsIgnoreCase(""))
changesSupport.firePropertyChange("resultTree", regEx.getResultTree(), regEx.applyRegEx(false, inputText.getText()));
}
/**
* applyPartialRegEx is used to apply the regex on the selected input text
* then fires the resultTree to the resultPanel and inputText
*/
public void applypartialRegEx() {
if (!inputText.getText().equalsIgnoreCase(""))
changesSupport.firePropertyChange("resultTree", regEx.getResultTree(), regEx.applyRegEx(true, inputText.getText()));
}
/**
* Creates and fire the regex tree representation
*/
public void updateRegExTree() {
changesSupport.firePropertyChange("regExTree", regEx.getParseTree(), regEx.updateRegExTree());
}
/**
* Open a regex file
*/
public void openRegExFile() {
// Ask to save if the current regex has been modified
if (regEx.isModified() && Application.settings.getAskForSave())
changesSupport.firePropertyChange("fileConflict", "", "rgx");
// or open the new regex file
else
changesSupport.firePropertyChange("openFile", "", "rgx");
}
/**
* Save a regex file
*/
public void saveRegExFile() {
changesSupport.firePropertyChange("saveFile", "", "rgx");
}
/**
* Undo last operation
*/
public void unDo() {
changesSupport.firePropertyChange("regEx", regEx.getRegularExpression(), regEx.unDo());
}
/**
* Redo last operation
*/
public void reDo() {
changesSupport.firePropertyChange("regEx", regEx.getRegularExpression(), regEx.reDo());
}
public void isValid(int indexS, int indexE) {
changesSupport.firePropertyChange("subValid", regEx.isSubValid(), regEx.checkSubValidity(indexS, indexE));
if(regEx.checkSubValidity(indexS, indexE) && Application.settings.getAutomaticPartialApply())
{
this.applypartialRegEx();
}
}
//--------------------------------------------------------------------------------------
// InputText methods
/**
* setText is called by the view to set the new value of the input text
* @param text
*/
public void setText(String text) {
// Set the new changed text
String oldText = inputText.getText();
changesSupport.firePropertyChange("inputText",oldText, inputText.setText(text));
}
public String getText() {
return inputText.getText();
}
public int setCaretPosition(int newValue) {
if(flagCaretEditing == false)
this.caretPosition = newValue;
return this.caretPosition;
}
/**
* Open a text file
*/
public void openTextFile() {
// Ask to save if the current text has been modified
if (inputText.isModified() && Application.settings.getAskForSave())
changesSupport.firePropertyChange("fileConflict", "", "txt");
// or open the new file
else
changesSupport.firePropertyChange("openFile", "", "txt");
}
/**
* Save a text file
*/
public void saveTextFile() {
changesSupport.firePropertyChange("saveFile", "", "txt");
}
/**
* setSelectedMatch is used to send to the inpuText which parts of string to highlight
* parts selected by the end-user through the resultPanel tree
* @param selection
*/
public void setSelectedMatch(ResultTreeNode selection) {
changesSupport.firePropertyChange("resultMatch", regEx.getSelectedMatch(), regEx.setSelectedMatch(selection));
}
//--------------------------------------------------------------------------------------
// general methods
/**
* Save a file (rgx or txt)
*/
public void saveFile(String filePath, String fileType) {
// if the provided path isn't null
if (filePath != null) {
try {
// check whether the extension has been added to the path
if (!filePath.toLowerCase().endsWith("."+fileType))
filePath += "."+fileType;
// create and fill the file
FileWriter output = new FileWriter(filePath);
if (fileType.equals("txt"))
{
output.write(inputText.getText());
inputText.setFilePath(filePath);
}
if (fileType.equals("rgx"))
{
output.write(regEx.getRegularExpression());
regEx.setFilePath(filePath);
}
output.flush();
output.close();
}
catch (IOException e) {
// Create the right error message from the extension type
String errorMessage = "\""+filePath+"\"\n"+Application.messages.getString("ERROR_SAVING_"+fileType.toUpperCase());
JOptionPane.showMessageDialog(null, errorMessage, Application.messages.getString("ERROR_SAVING_TITLE"), JOptionPane.ERROR_MESSAGE);
}
}
}
/**
* Open a file (rgx or txt)
*/
public void openFile(String filePath, String fileType) {
if (filePath != null) {
try {
File textFile = new File(filePath);
InputStream fileStream = new FileInputStream(filePath);
// Create the byte array to hold the data
long length = textFile.length();
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fileStream.read(bytes, offset, bytes.length-offset)) >= 0)
offset += numRead;
// Ensure all the bytes have been read in
if (offset < bytes.length)
throw new IOException("Could not completely read file "+textFile.getName());
// Close the input stream
fileStream.close();
// Write bytes in the var
String content = new String(bytes);
// Put it in the right model
if (fileType.equals("rgx")) {
// fire the changed property
this.setRegEx(content);
// Update the state of the file
regEx.setFilePath(filePath);
}
if (fileType.equals("txt")) {
// fire the changed property
changesSupport.firePropertyChange("inputText", inputText.getText(), inputText.setText(content));
// Update the state of the file
inputText.setFilePath(filePath);
}
}
catch (java.lang.IllegalArgumentException e) {
System.out.println("Could not render RegEx tree.");
}
catch (Exception e) { System.out.println(e);
// Create the right error message from the extension type
String errorMessage = "\""+filePath+"\"\n"+Application.messages.getString("ERROR_LOADING_"+fileType.toUpperCase());
JOptionPane.showMessageDialog(null, errorMessage, Application.messages.getString("ERROR_LOADING_TITLE"), JOptionPane.ERROR_MESSAGE);
}
}
}
public boolean isRegExModified() {
return regEx.isModified();
}
public boolean isTextModified() {
return inputText.isModified();
}
/**
* Export the RegEx to an external file
* @param name
* @param language
* @param path
*/
public void export(String name, String language, String filePath, boolean text) {
if(text)
export(name, language, filePath, inputText.getText());
else
export(name, language, filePath, "text to match");
}
/**
* Export the RegEx to an external file
* @param name
* @param language
* @param path
* @param text
*/
public void export(String name, String language, String filePath, String text) {
try {
File templateFile = new File("templates/"+language+".template");
InputStream fileStream = new FileInputStream("templates/"+language+".template");
// Create the byte array to hold the data
long length = templateFile.length();
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fileStream.read(bytes, offset, bytes.length-offset)) >= 0)
offset += numRead;
// Ensure all the bytes have been read in
if (offset < bytes.length)
throw new IOException("Could not completely read file "+templateFile.getName());
// Close the input stream
fileStream.close();
// Write bytes in the var
String code = new String(bytes);
code = code.replaceAll("GTLName", name);
code = code.replaceAll("GTLRegEx", addSlashes(regEx.getRegularExpression()));
code = code.replaceAll("GTLText", addSlashes(text));
//Check whether the extension has been added to the path
String fileType = Application.settings.getExportLanguages().get(language);
if (!filePath.toLowerCase().endsWith("."+fileType))
filePath += "."+fileType;
//create and fill the final file
FileWriter output = new FileWriter(filePath);
output.write(code);
output.flush();
output.close();
}
catch (Exception e) {
// Create the right error message from the extension type
String errorMessage = "\""+filePath+"\"\n"+Application.messages.getString("ERROR_SAVING_TXT");
JOptionPane.showMessageDialog(null, errorMessage, Application.messages.getString("ERROR_SAVING_TITLE"), JOptionPane.ERROR_MESSAGE);
}
changesSupport.firePropertyChange("readyToExport", "", "ready");
}
private String addSlashes(String text) {
text = text.replace("\\", "\\\\");
text = text.replace("\"", "\\\"");
return text;
}
//--------------------------------------------------------------------------------------
// property change methods
public void addPropertyChangeListener(java.beans.PropertyChangeListener pcl) {
changesSupport.addPropertyChangeListener(pcl);
}
public void removePropertyChangeListener(java.beans.PropertyChangeListener pcl) {
changesSupport.removePropertyChangeListener(pcl);
}
}