So I have a program where you can log in and add/remove friends to and from the friends arraylist. Also I can like a certain thing and that thing will be stored into the likes arraylist. I'm asked to make undo and redo options for whichever action I do.
So I want to add apple as a friend. After that when I select the undo option, I can undo that action so apple wouldn't be my friend. How I can approach this with a Command Pattern when the input is whatever name or word I inputted to store into the friends arraylist?
I did some research and found that using a command pattern could be my best bet since this has to be done under the Facebook Class I already have. I'm assuming I'll have to use two different stacks, but I'm getting a bit lost in the topic.
I decided to add parts of what I have so that I can get a bit more help on what I need to do and what my program does.
In the driver program
Facebook facebook1 = new Facebook();
if (userInput == 6)
{
System.out.println("Login");
String operand1 = getOperand("What is the Username? ");
String operand2 = getOperand("What is the Password? ");
System.out.println("Enter a friend to be added. ");
String operand3 = getOperand("What is the Username? ");
facebook1.friend(operand3);
}
if (userInput == 7)
{
System.out.println("Login");
String operand1 = getOperand("What is the Username? ");
String operand2 = getOperand("What is the Password? ");
System.out.println("Enter a friend to be removed. ");
String operand3 = getOperand("What is the Username? ");
facebook1.defriend(operand3);
}
if (userInput == 12)
{
System.out.println("Login");
String operand1 = getOperand("What is the Password? ");
facebook1.undo();
}
if (userInput == 13)
{
System.out.println("Login");
String operand1 = getOperand("What is the Password? ");
facebook1.redo();
}
In the Facebook Class
ArrayList<FacebookUser> recommendedFriends = new ArrayList<FacebookUser>();
void friend(String newFriend)
{
boolean positiveChecker = false;
for (int i = 0; i < recommendedFriends.size(); i++)
{
if (recommendedFriends.get(i).toString().equalsIgnoreCase(newFriend))
{
System.out.println("Error: This friend already exists.");
positiveChecker = true;
}
}
if (positiveChecker == false)
{
FacebookUser friend = new FacebookUser(newFriend, newFriend );
recommendedFriends.add(friend);
System.out.println(friend + " is now your friend.");
}
positiveChecker = false;
}
void defriend(String formerFriend)
{
boolean positiveChecker = false;
for (int i = 0; i < recommendedFriends.size(); i++)
{
if (recommendedFriends.get(i).toString().equalsIgnoreCase(formerFriend))
{
recommendedFriends.remove(i);
System.out.println(formerFriend + " has been removed from your friends list.");
positiveChecker = true;
}
if (recommendedFriends.size() == (i + 1) && recommendedFriends.get(i).toString() != formerFriend
&& positiveChecker == false)
{
System.out.println("Error: There is no friend with this username.");
}
}
positiveChecker = false;
}
public interface Command
{
public void undo();
public void redo();
}
When you undo 2 things then do a completely new action, you need to "forget" the "redo history" and replace it with the new command, right?
For example...
Add Friend Jim
Add Friend Bill
Add Friend Jill
Remove Jim
Undo
Undo
State should be "Jim" and "Bill".
So you only really need one list and a pointer to the current "command", for example...
// Note: NOT thread safe!
public class CommandStack {
private List<Command> commands = Collections.emptyList();
private int nextPointer = 0;
public void doCommand(Command command) {
List<Command> newList = new ArrayList<>(nextPointer + 1)
for(int k = 0; k < nextPointer; k++) {
newList.add(commands.get(k));
}
newList.add(command);
commands = newList;
nextPointer++;
// Do the command here, or return it to whatever called this to be done, or maybe it has already been done by now or something
// (I can only guess on what your code currently looks like...)
command.execute();
}
public boolean canUndo() {
return nextPointer > 0;
}
public void undo() {
if(canUndo()) {
nextPointer--;
Command commandToUndo = commands.get(nextPointer);
// Undo the command, or return it to whatever called this to be undone, or something
command.undo();
} else {
throw new IllegalStateExcpetion("Cannot undo");
}
}
public boolean canRedo() {
return nextPointer < commands.size();
}
public void redo() {
if(canRedo()) {
commandToDo = commands.get(nextPointer);
nextPointer++;
// Do the command, or return it to whatever called this to be re-done, or something
commandToDo.execute();
} else {
throw new IllegalStateException("Cannot redo");
}
}
}
If I had...
interface Command { /* execute / undo etc */ }
public class AddFriendCommand implements Command {
private String friendName;
// ... other fields, constructor / getters etc ...
public void execute() {
// Actually do it...
System.out.println("Added friend " + name);
}
public void undo() {
// Undo it...
System.out.println("Removed friend " + name);
}
}
public class RemoveFriendCommand implements Command {
private String friendName;
// ... other fields, constructor / getters etc ...
public void execute() {
// Actually do it, maybe throw exception if friend does not exist?
// (that would have to be a runtime exception unless you want the interface's method to throw stuff);
System.out.println("Removed friend " + name);
}
public void undo() {
// Undo it...
System.out.println("Added friend " + name);
}
}
You could repeat the sequence above using...
CommandStack stack = new CommandStack();
stack.doCommand(new AddFriendCommand("Jim"));
stack.doCommand(new AddFriendCommand("Bill"));
stack.doCommand(new AddFriendCommand("Jill"));
stack.doCommand(new RemoveFreindCommand("Jim"));
stack.undo();
stack.undo();
If you now did a new command (via doCommand) it would forget that you ever added "Jill" or removed "Jim", but instead would now remember the new command and the rest of the command history that was not undone.
Hope this helps.
You are misunderstanding how the command pattern works. You want to have a separate List of your Commands, where each instance of Command represents an action.
So you would want to have something like:
List<Command> actionStack;
and then have stuff like
public class AddCommand implements Command {
private final void List<FacebookUser> userList;
private final void FacebookUser newUser;
public AddCommand(List<FacebookUser> userList, FacebookUser newUser) {
this.userList = userList;
this.newUser = newUser;
}
#Override
public void undo() {
userList.remove(newUser);
}
#Override
public void redo() {
userList.add(newUser);
}
}
I'm new in coding and I have a problem to understand something. I follow the example form Parse.com Doc and wrote this.
public void getData() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseClass");
query.getInBackground("lxFzCTeOcl", new GetCallback<ParseObject>() {
public void done(ParseObject parseObject, ParseException e) {
if (e == null) {
String object = parseObject.getString("value");
int object_value = Integer.parseInt(obiect);
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
I understand this like:
I send query to server
get obiect with "lxFzCTeOcl" id
if there is no exception I create String object which takes string
form "value" column.
convert String to int
My question is: How can I use object_value for example to make a chart or put it into a table?
Here we will add the array list to your code and start to store an object inside the array every time we call the getData method in your class.
private ArrayList<Integer> dataArray;
public void getData() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("ParseClass");
query.getInBackground("lxFzCTeOcl", new GetCallback<ParseObject>() {
public void done(ParseObject parseObject, ParseException e) {
if (e == null) {
String object = parseObject.getString("value");
Integer objectValue = Integer.parseInt(obiect);
if(dataArray==null)
dataArray = new ArrayList<Integer>();
dataArray.add(objectValue);
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
And here I'm just adding a simple example of how to create a simple pie chart using our array list (note that I used the lib AChartEngine http://www.achartengine.org/):
private static int[] COLORS = new int[] { Color.GREEN, Color.BLUE,Color.MAGENTA, Color.CYAN };
private GraphicalView createPieChart(ArrayList<Integer> data){
GraphicalView chartView;
CategorySeries series = new CategorySeries("PIE");
for (int i = 0; i < VALUES.length; i++) {
series.add(i, data.get(i));
SimpleSeriesRenderer renderer = new SimpleSeriesRenderer();
renderer.setColor(COLORS[(series.getItemCount() - 1) % COLORS.length]);
mRenderer.addSeriesRenderer(renderer);
}
chartView = ChartFactory.getPieChartView(this, series, new DefaultRenderer());
chartView.repaint();
return chartView;
}
Now you can add this GraphicalView to your view.
The returned object is much like a map, with key/value pairs. In your example, the key is "value", which makes it a little confusing, but it would be like this if you wanted all fields:
for (Field field : myInstance.getClass().getDeclaredFields()) {
String name = field.getName();
value = field.get(myInstance).toString();
map.put(name, value);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have Java Swing application which is designed in poor architecture.
GUI, SQL Statement ... etc, all one class.
Ex. NewEmployee.java have GUI, SQL insert,update,delete & select in this class, there is no separation.
From what I read we should separate the logic from the design.
To be honest I don't know how to do that, or how to understand it.
I need to know how to break down my project so I got : model, view & controller, but I need to know what each one mean & how each one should cooperate with other.
could you help in separating this:
public class PendingOInvoices extends CFrame {
private static final long serialVersionUID = 1L;
private JToolBar toolBar = new JToolBar();
private JPanel panel_1 = new JPanel();
private JLabel label3 = new JLabel();
private CText cSearch = new CText();
private JLabel label2 = new JLabel();
private CDCombo cSearchBy = new CDCombo();
private CBGeneral cMakeBill = new CBGeneral();
private Component component5_1 = Box.createHorizontalStrut(3);
private CBRefreshE cRefresh = new CBRefreshE();
private CBCloseE cClose = new CBCloseE();
private Component component5_3 = Box.createHorizontalStrut(3);
private JLabel label1 = new JLabel();
private CDate cTDate = new CDate();
private MyOutBillingModel model1 = new MyOutBillingModel();
private JPVTableView table1 = new JPVTableView(model1);
private JLabel label = new JLabel();
private CDate cFDate = new CDate();
private CBNewE cNew = new CBNewE();
private CBModifyE cModify = new CBModifyE();
private Component component5 = Box.createHorizontalStrut(3);
private Component component5_2 = Box.createHorizontalStrut(3);
private JLabel label4 = new JLabel();
private CDCombo cFilter = new CDCombo();
public PendingOInvoices () {
setTitle("Out Patients - Pending Encounters");
setFrameIcon("opdbilling");
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
setSize(new Dimension(980, 546));
getContentPane().setLayout(new BorderLayout());
getContentPane().add(panel_1, BorderLayout.NORTH);
panel_1.setMaximumSize(new Dimension(0, 44));
panel_1.setMinimumSize(new Dimension(0, 44));
panel_1.setLayout(null);
panel_1.setPreferredSize(new Dimension(0, 44));
panel_1.add(label3);
label3.setText("Search engine:");
label3.setBounds(790, 0, 170, 19);
panel_1.add(cSearch);
cSearch.addKeyListener(new CSearchKeyListener());
cSearch.setBounds(790, 20, 170, 23);
panel_1.add(label2);
label2.setText("Search by:");
label2.setBounds(662, 0, 127, 19);
panel_1.add(cSearchBy);
cSearchBy.addActionListener(new CSearchByActionListener());
cSearchBy.setBounds(662, 20, 127, 23);
cSearchBy.addItem("ID No");
cSearchBy.addItem("File No");
cSearchBy.addItem("Patient Name (EN)");
cSearchBy.addItem("Patient Name (ع)");
cSearchBy.addItem("Encounter No");
toolBar.setBounds(0, 0, 264, 45);
panel_1.add(toolBar);
toolBar.setFloatable(false);
toolBar.add(cRefresh);
toolBar.add(component5_1);
toolBar.add(cNew);
cNew.addActionListener(new CNewActionListener());
toolBar.add(component5_3);
toolBar.add(cModify);
cModify.addActionListener(new CModifyActionListener());
toolBar.add(component5);
toolBar.add(cMakeBill);
cMakeBill.setText("Make Bill");
cRefresh.addActionListener(new CRefreshActionListener());
cMakeBill.setIcon(SwingResourceManager.getIcon(PendingOInvoices.class, "/images/small/billmaker.png"));
cMakeBill.addActionListener(new CMakeBillActionListener());
toolBar.add(component5_2);
toolBar.add(cClose);
cClose.addActionListener(new CCloseActionListener());
panel_1.add(label1);
label1.setText("To Date:");
label1.setBounds(382, 0, 115, 19);
panel_1.add(cTDate);
cTDate.addTextListener(new CTDateTextListener());
cTDate.addKeyListener(new CTDateKeyListener());
cTDate.setBounds(382, 20, 115, 23);
getContentPane().add(table1);
table1.getJTable().addMouseListener(new table1JTableMouseListener());
table1.getJTable().addKeyListener(new Table1JTableKeyListener());
cSearch.setHorizontalAlignment(SwingConstants.CENTER);
panel_1.add(label);
label.setText("From Date:");
label.setBounds(266, 0, 115, 19);
panel_1.add(cFDate);
cFDate.setText("01/01/"+cTDate.getText().substring(7));
cFDate.addTextListener(new CFDateTextListener());
cFDate.addKeyListener(new CFDateKeyListener());
cFDate.setBounds(266, 20, 115, 23);
panel_1.add(label4);
label4.setText("Filtering Options:");
label4.setBounds(498, 0, 163, 19);
panel_1.add(cFilter);
cFilter.addActionListener(new CFilterActionListener());
cFilter.setBounds(498, 20, 163, 23);
cFilter.addItem("--- Choose ---");
cFilter.addItem("Guarantors Shares Only");
cFilter.addItem("Cash Patients Only");
cFilter.addItem("Patients Got Discount Only");
setWidths();
fillEncounters();
}
public void updateMe(String encno){
fillEncounters();
table1.getTable().requestFocus();
table1.getTable().setFocusCell(table1.search(encno, 1),1);
}
private void setWidths() {
model1.setColumnCount(9);
model1.setRowCount(0);
table1.getColumn(0).setPreferredWidth(75);
table1.getColumn(1).setPreferredWidth(90);
table1.getColumn(2).setPreferredWidth(350);
table1.getColumn(3).setPreferredWidth(80);
table1.getColumn(4).setPreferredWidth(80);
table1.getColumn(5).setPreferredWidth(80);
table1.getColumn(6).setPreferredWidth(80);
table1.getColumn(7).setPreferredWidth(80);
table1.getColumn(8).setPreferredWidth(20);
table1.getColumn(0).setHeaderValue("Date");
table1.getColumn(1).setHeaderValue("Encounter No");
table1.getColumn(2).setHeaderValue("Patient Name");
table1.getColumn(3).setHeaderValue("Total");
table1.getColumn(4).setHeaderValue("Guarantors");
table1.getColumn(5).setHeaderValue("Discount");
table1.getColumn(6).setHeaderValue("Paid");
table1.getColumn(7).setHeaderValue("Balance");
table1.getColumn(8).setHeaderValue("");
table1.setColumnType(0, JPVTable.DATE, null);
table1.setColumnType(1, JPVTable.DATE, null);
table1.setColumnType(2, JPVTable.TEXT, null);
table1.setColumnType(3, JPVTable.DOUBLE, null);
table1.setColumnType(4, JPVTable.DOUBLE, null);
table1.setColumnType(5, JPVTable.DOUBLE, null);
table1.setColumnType(6, JPVTable.DOUBLE, null);
table1.setColumnType(7, JPVTable.DOUBLE, null);
table1.setColumnType(8, JPVTable.BOOLEAN, null);
CTableConfig mc = new CTableConfig();
mc.newConfigureTable(table1,8,0,true);
table1.getTable().getColumnModel().getColumn(8).setHeaderRenderer(new CHGeneral(new MyItemListener()));
}
class MyItemListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
if (!(source instanceof AbstractButton)) return;
boolean checked = e.getStateChange() == ItemEvent.SELECTED;
int rows = model1.getRowCount();
for(int x = 0; x < rows; x++){
model1.setValueAt(checked,x,8);
}
}
}
private String getSearchColumn(){
if(cSearchBy.getSelectedIndex() == 0){
return "patients.PatID";
}else if(cSearchBy.getSelectedIndex() == 1){
return "encounters.Enc_Patient";
}else if(cSearchBy.getSelectedIndex() == 2){
return "concat(patients.PatFirst,' ', patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily)";
}else if(cSearchBy.getSelectedIndex() == 3){
return "concat(patients.PatFirstA,' ', patients.PatFatherA,' ',patients.PatMiddleA,' ',patients.PatFamilyA)";
}else if(cSearchBy.getSelectedIndex() == 4){
return "encounters.Enc_No";
}
return "";
}
private void fillEncounters(){
String currentValue = "";
int r = table1.getTable().getFocusRow();
cFDate.setFormat(2);
cTDate.setFormat(2);
String sql = "SELECT \n"
+"Date_Format(Enc_Date,'%d/%m/%Y'), \n"
+"encounters.Enc_No, \n"
+"CONCAT(' ',patients.PatFirst,' ',patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily), \n"
+"FORMAT((Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED),2), \n"
+"FORMAT(Enc_Guarantor,2), \n"
+"FORMAT(Enc_Discount,2), \n"
+"FORMAT((Enc_Receipt-Enc_Payment),2), \n"
+"FORMAT(Enc_Balance,2), \n"
+""+Boolean.FALSE+", \n"
+"encounters.Enc_Patient, \n"
+"VERSION \n"
+"FROM \n"
+"encounters \n"
+"INNER JOIN encsummary ON encounters.Enc_No = encsummary.Enc_No \n"
+"INNER JOIN patients ON encounters.Enc_Patient = patients.PatNo \n"
+"WHERE Enc_Date Between '"+cFDate.getText()+"' AND '"+cTDate.getText()+"' AND Enc_Billed = 'false' \n"
+"AND (Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED) > 0 \n";
if(cFilter.getSelectedIndex() == 1){
sql+="and Enc_Guarantor > 0 \n";
}else if(cFilter.getSelectedIndex() == 2){
sql+="and Enc_Guarantor = 0 \n";
}else if(cFilter.getSelectedIndex() == 3){
sql+="and Enc_Discount > 0 \n";
}
if(cSearch.getText().trim().length() > 0){
sql+= "and "+getSearchColumn()+" LIKE '%"+cSearch.getText()+"%' \n";
}
sql+="Order By encounters.Enc_No DESC";
cFDate.setFormat(1);
cTDate.setFormat(1);
model1.setData(CDeclare.dataAccessor.getData(sql));
try{
currentValue = table1.getValueAt(r, 1).toString();
}catch(Exception ex){}
int i = table1.search(currentValue, 1);
table1.getTable().scrollRectToVisible(new Rectangle(table1.getTable().getCellRect(i, 1, true)));
table1.getTable().changeSelection(i, 1, false, false);
}
private class CSearchByActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
cSearchBy_actionPerformed(arg0);
}
}
private class table1JTableMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent arg0) {
table1JTable_mouseClicked(arg0);
}
}
private class CMakeBillActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cMakeBill_actionPerformed(e);
}
}
private class CSearchKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cSearch_keyReleased(e);
}
}
private class CTDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cTDate_keyReleased(e);
}
}
private class CRefreshActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cRefresh_actionPerformed(e);
}
}
private class CTDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cTDate_textValueChanged(e);
}
}
private class CCloseActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cClose_actionPerformed(e);
}
}
private class CFDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cFDate_keyReleased(e);
}
}
private class CFDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cFDate_textValueChanged(e);
}
}
private class CNewActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cNew_actionPerformed(e);
}
}
private class CModifyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cModify_actionPerformed(e);
}
}
private class Table1JTableKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
table1JTable_keyPressed(e);
}
}
private class CFilterActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cFilter_actionPerformed(e);
}
}
protected void cSearchBy_actionPerformed(ActionEvent arg0) {
if(cSearchBy.getSelectedIndex() == 3){
cSearch.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}else{
cSearch.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
}
cSearch.setText(null);
}
protected void table1JTable_mouseClicked(MouseEvent e) {
int c = table1.getTable().getSelectedColumn();
if(e.getClickCount() >= 2 && c != 8){
cModify_actionPerformed(null);
}
}
private void insertInvoice(){
double total = 0,guarantors = 0,grandtotal = 0;
CDate datg = new CDate();
String encno = "",invno = "",version = "";
for(int i = 0; i < model1.getRowCount();i++){
if(model1.getValueAt(i, 8).equals(Boolean.TRUE)){
if(datg.getFormat() != 1){
datg.setFormat(1);
}
encno = model1.getValueAt(i, 1).toString();
version = model1.getValueAt(i, 10).toString();
if(!CDeclare.SAMEVERSION("encounters","Enc_No",encno,version)){
return;
}
CDeclare.dataAccessor.UpdateDB("update encounters set VERSION = (VERSION+1) WHERE Enc_No = '"+encno+"'");
CDeclare.doubleValue.setValue(model1.getValueAt(i,3));
total = CDeclare.doubleValue.getDouble();
CDeclare.doubleValue.setValue(model1.getValueAt(i,4));
guarantors = CDeclare.doubleValue.getDouble();
grandtotal = total-guarantors;
invno = CDeclare.newNumber.getLastYearMonthNo(datg, "LastTemp");
datg.setFormat(2);
String sql = " Insert into invoice(Inv_No,Inv_Entry_Date,Inv_Kind,Inv_ClientKind,Inv_ClientSubKind,Inv_SubRefNo,Inv_Name,Inv_Date," +
"Inv_VatPercent,Inv_SubTotal,Inv_OthersTotal,Inv_Total,EMPIII) values (" +
"'" + invno + "'," +
"'" + CDeclare.getServerDateMySSQL() + "'," +
"'" + "S" + "'," +
"'" + "P" + "'," +
"'" + "OP" + "'," +
"'" + encno + "'," +
"'" + model1.getValueAt(i, 9) + "'," +
"'" + datg.getText() + "'," +
"'" + CDeclare.VAT + "'," +
"'" + total + "'," +
"'" + guarantors + "'," +
"'" + grandtotal + "'," +
"'" + CDeclare.EMPNO + "'" + ")";
CDeclare.dataAccessor.InsertDB(sql);
insertInvDetails(encno,invno);
}
}
}
private void insertInvDetails(String encno,String invno){
CCurrency vat = new CCurrency();
String invDetSql = "SELECT \n"
+"Sec_Account, \n"
+"Sec_Department, \n"
+"Ch_Kind, \n"
+"FORMAT((SUM(Ch_Total)/("+(1+CDeclare.VAT)+")),2), \n"
+"FORMAT(SUM(Ch_Total),2) \n"
+"FROM \n"
+"enccharges \n"
+"INNER JOIN medicalsections ON Ch_Section = Sec_No \n"
+"WHERE \n"
+"Ch_EncNo = '"+encno+"' \n"
+"GROUP BY Ch_Kind,Sec_Account,Sec_Department for update \n";
Vector<?> data = CDeclare.dataAccessor.getData(invDetSql);
for(int i = 0; i < data.size(); i++){
Vector<?> v = (Vector<?>) data.elementAt(i);
CDeclare.myDouble.setValue(v.elementAt(4));
CDeclare.doubleValue.setValue(v.elementAt(3));
vat.setDouble(vat.getDouble()+CDeclare.myDouble.getDouble()-CDeclare.doubleValue.getDouble());
String insSql = "Insert into invoicedetails(Inv_No,Inv_Account,Inv_Department,Inv_Kind,Inv_Total,Inv_TaxTotal) values (" +
"'" + invno + "'," +
"'" + v.elementAt(0) + "'," +
"'" + v.elementAt(1) + "'," +
"'" + v.elementAt(2) + "'," +
"'" + CDeclare.doubleValue.getDouble() + "'," +
"'" + CDeclare.myDouble.getDouble()+ "'" + ")";
CDeclare.dataAccessor.InsertDB(insSql);
}
CDeclare.dataAccessor.UpdateDB("update invoice set Inv_Vat = '"+vat.getDouble()+"' where Inv_No = '"+invno+"'");
String sqlUpdateEncounter = " Update encounters set \n" +
" Enc_Billed = 'true',\n" +
" Enc_Status = 'D',\n" +
" Enc_BillNo = '" + invno + "'\n " +
" where Enc_No = '" + encno + "'";
CDeclare.dataAccessor.UpdateDB(sqlUpdateEncounter);
}
protected void cMakeBill_actionPerformed(ActionEvent e) {
int option = (new CConfirms()).getSelection('S',"This operation will generate temporary invoices for selected encounters \n Are you sure ?!!!");
if(option != 0){
return;
}
CDeclare.dataAccessor.initAutoCommit();
CDeclare.dataAccessor.beginTransaction();
insertInvoice();
if(CDeclare.exCounter == 0){
CDeclare.dataAccessor.endTransaction();
fillEncounters();
}else{
CDeclare.dataAccessor.rollBack();
new CAlerts('D');
}
}
protected void cSearch_keyReleased(KeyEvent e) {
fillEncounters();
}
protected void cTDate_keyReleased(KeyEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cRefresh_actionPerformed(ActionEvent e) {
fillEncounters();
}
protected void cTDate_textValueChanged(TextEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cClose_actionPerformed(ActionEvent e) {
dispose();
}
protected void cFDate_keyReleased(KeyEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cFDate_textValueChanged(TextEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cNew_actionPerformed(ActionEvent e) {
NewEncounter newr = new NewEncounter(getTitle() + " - "+cNew.getText());
newr.insertMode();
newr.setOwner(this);
newr.setVisible(true);
}
protected void cModify_actionPerformed(ActionEvent e) {
int r = table1.getTable().getFocusRow();
String encno = model1.getValueAt(r,1).toString();
NewEncounter newr = new NewEncounter(getTitle() + " - "+cModify.getText());
newr.modifyMode();
newr.setOwner(this);
newr.fillEncounter(encno);
newr.setVisible(true);
}
protected void table1JTable_keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
e.consume();
cModify_actionPerformed(null);
}
}
protected void cFilter_actionPerformed(ActionEvent e) {
fillEncounters();
}
}
class MyOutBillingModel extends PVTableModel {
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int iRow, int iCol) {
try{
if(iCol == 8){
return true;
}
}catch(Exception ex){}
return false;
}
Your on the right track if you know what MVC is. You may also want to look at MVVM as it has the same goal. Let's break it down:
Model - simple classes with getter/setters and no logic or details about storage
View - classes or pages that display Model data in some organized way
Controller - the object that accepts actions from the View, manipulates Model, and transfers control to a new View (passing it a Model)
In general what we like to do is first "model" the data into classes that have no business logic, UI concepts or storage dependencies (like SQL). They are simple objects with getter/setter for data. Then the "view" classes/pages are designed so they know how to read those model objects and display them in whatever way makes sense. But the view does not know where/how those model objects are stored. The glue that puts the view and model together is the "controller", which is why it has that name. Typically the user interacts with the view to get/change data, and the view then invokes the controller with an "action" like "get-employee". The control is the only thing that knows what the action means and what to do. In the simple case, the controller will go get the data from the storage, and then decide on what the next view should be for the user. It takes the model object it loaded from storage, constructs the view, and passes the model to the view where it is rendered. The key point here is that the first view has no idea of what the controller is going to do and has no idea what the next view will be. That's all the business of the controller.
So in your case, you might have a few Employee Views like NewEmployee, EmployeeDetails, EmployeeListing. And then you might have a Model like Employee. You should be able to build these views with no SQL. That's how you know you are doing this right. Then, you introduce the Controller, like an EmployeeController. Then, you tie Button presses and click events in your Views to the action methods on the Controller. So you can add methods like this:
View listEmployees()
View createEmployee(Employee e)
View getEmployee(long id)
View deleteEmployee(long id)
Your Controller should then be the only component that interacts with storage, and then decides on what the "next" View should be. That's why it returns a View and not the Model. For instance, the method might look something like this:
public class EmployeeController {
. . .
public View listEmployees() {
List<Employee> employees = storage.getAllEmployees();
return new EmployeeListing(employees);
}
}
That's the basic concept and how the separation works. In most real MVC/MVVC frameworks, there is more sophistication around the mapping of actions and views.
Notice I also added a "storage" object so that even the Controller does not know that SQL is used. That will lead you to concepts like DAO which is how to abstract the actual storage details away from the rest of the app, if you want to.
Model View Controller (MVC) is a concept you may want to use. More about that in here: How to correctly implement swing-Please check the accepted answer in this link.
In your case, don't break the working code unless you have to...Remember that such a design change may cost more that its worth for a running system.
Start by separating all the SQL code into a separate package with interfaces and implementations. You can test those without the UI and put them aside.
Then I'd recommend making all the Swing classes another separate package. Do not call new to create and attach Listeners in the Swing classes. Instead, provide a mechanism for passing them in via constructors or setters. Inject those dependencies.
Model classes ought to represent the problem you're solving without a UI or database. See if they do.
Last have the controller package with classes that instantiate the listeners and views, gives the views the listeners they need, and fulfill the use cases by manipulating model and persistence objects.
That's MVC.
from what i read we should separate the logic from the design.
to be honest i don't know how to do that, or how to understand it.
The main reason (beyond the usual "cleaner code and architecture") why you want to do that and the principles behind can be explained best on an example.
Let's assume, you have a nice working desktop UI application. Now you want to create a web version of the very same application.
When the GUI application has placed all the business logic and all the DB accesses in the forms (or whatever the equivalent is), you got a problem. Because everything is coupled so tightly together, it is virtually impossible to re-use anything from the GUI application. So you start duplicating your code, and that's a real bad-bad. That way you end up with two code bases which have to be maintained.
In order to get the most out of the reusing game, you want to separate (at least) the UI from the underlying business logic. And while we're at it, it is also not such a bad idea to split the levels of abstraction once more and extracting the data model.
Now we can do something like this:
+-----------+
| Web UI |<<------+
+-----------+ |
| +-----------+ +------------+
+----->>| Biz Logic |<<---->>| Data Model |
| +-----------+ +------------+
+-----------+ |
| GUI |<<------+
+-----------+
To achieve that, you have to do certain things:
split the code accordingly to have independent (code) modules
remove all dependencies from right hand parts to left hand parts (ie. logic should not know anything about the UI details)
Methodical frameworks like MVC or MVVM or others can be considered as best-practice toolbelts to support you doing that at the interface between the logic and the UI parts. These concepts are proven and have matured over a long time. Strictly speaking, it is not required that you follow these concepts, but it is strongly recommended, as they not only help with architectural decisions but also and the make day-to-day coding work much easier, because of the existing framework implementations (again, that varies on what language etc. is used).