Question

I have created an application that refers to a list of users, allocated from an XML file to a JTree component, which can then be viewed and edited accordantly. My code so far:

public class DomainModel extends JFrame {

    private JTree tree;
    private String fileSource = "users.xml";
    private NodeList listOfUsers;
    private String objID;

    private JTextField textName;
    private JTextField textAge;
    private JTextField textDOB;
    private JButton editBtn;

    private JTextField textEditName;
    private JTextField textEditAge;
    private JTextField textEditDOB;
    private JButton saveBtn;
    private JButton cancelBtn;

    public DomainModel() {

        createGUI();
    }

    public void createGUI() {

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new GridLayout(1, 2));

        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new GridLayout(1, 1));
        leftPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Domain Model"),
                BorderFactory.createEmptyBorder(10, 10, 10, 10)));

        createTree();

        tree.setLayout(new GridLayout(1, 1));
        tree.setBorder(new EmptyBorder(10, 10, 10, 10));
        tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {

            public void valueChanged(TreeSelectionEvent e) {

                nodeChange(e);
            }
        });

        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new GridLayout(2, 1));

        JPanel detailsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        detailsPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Node Details"),
                BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        JLabel labelName = new JLabel("Name");
        JLabel labelAge = new JLabel("Age");
        JLabel labelDOB = new JLabel("DOB");

        textName = new JTextField(15);
        textAge = new JTextField(15);
        textDOB = new JTextField(15);

        editBtn = new JButton("Edit");
        editBtn.addActionListener(new ButtonListener());

        detailsPanel.add(labelName);
        detailsPanel.add(textName);
        detailsPanel.add(labelAge);
        detailsPanel.add(textAge);
        detailsPanel.add(labelDOB);
        detailsPanel.add(textDOB);
        detailsPanel.add(editBtn);

        JPanel editPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        editPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Edit Node"),
                BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        JLabel labelEditName = new JLabel("Name");
        JLabel labelEditAge = new JLabel("Age");
        JLabel labelEditDOB = new JLabel("DOB");

        textEditName = new JTextField(15);
        textEditAge = new JTextField(15);
        textEditDOB = new JTextField(15);

        saveBtn = new JButton("Save");
        saveBtn.addActionListener(new ButtonListener());

        cancelBtn = new JButton("Cancel");
        cancelBtn.addActionListener(new ButtonListener());

        editPanel.add(labelEditName);
        editPanel.add(textEditName);
        editPanel.add(labelEditAge);
        editPanel.add(textEditAge);
        editPanel.add(labelEditDOB);
        editPanel.add(textEditDOB);
        editPanel.add(saveBtn);
        editPanel.add(cancelBtn);

        leftPanel.add(new JScrollPane(tree));
        rightPanel.add(detailsPanel);
        rightPanel.add(editPanel);
        mainPanel.add(leftPanel);
        mainPanel.add(rightPanel);
        mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
        add(mainPanel);

        nullDetails();
        nullEdit();

        setTitle("Domain Model Example");
        setSize(525, 350);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
    }

    public void createTree(){

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("users");

        try {

            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(new File(fileSource));

            listOfUsers = doc.getElementsByTagName("user"); 

            // for each user in the node list, add it to the JTree
            for (int i = 0; i < listOfUsers.getLength(); i++) {

                Element el = (Element) listOfUsers.item(i);
                String id = el.getAttribute("id");
                File file = new File(id);
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(file);
                root.add(node);
            }

            tree = new JTree(root);

        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    public void nodeChange(TreeSelectionEvent e) {

        nullDetails();
        nullEdit();

        objID = e.getPath().getLastPathComponent().toString();

        // for each user in the node list, find an ID match
        for (int i = 0; i < listOfUsers.getLength(); i++) {

            Element el = (Element) listOfUsers.item(i);
            String strID = el.getAttribute("id");

            // if an ID match has been found, display it's details
            if (objID.equals(strID)) {

                String strName = el.getElementsByTagName("name").item(0).getTextContent();
                String strAge= el.getElementsByTagName("age").item(0).getTextContent();
                String strDOB = el.getElementsByTagName("dob").item(0).getTextContent();

                textName.setText(strName);
                textAge.setText(strAge);
                textDOB.setText(strDOB);
                editBtn.setEnabled(true);
                break;
            }
        }
    }

    public void nullDetails() {

        textName.setText(null);
        textAge.setText(null);
        textDOB.setText(null);

        textName.setEnabled(false);
        textAge.setEnabled(false);
        textDOB.setEnabled(false);

        editBtn.setEnabled(false);
    }

    public void nullEdit() {

        textEditName.setText(null);
        textEditAge.setText(null);
        textEditDOB.setText(null);

        textEditName.setEnabled(false);
        textEditAge.setEnabled(false);
        textEditDOB.setEnabled(false);

        saveBtn.setEnabled(false);
        cancelBtn.setEnabled(false);
    }

    class ButtonListener implements ActionListener {

        public void actionPerformed(ActionEvent a) {

            JButton b = (JButton) a.getSource();
            String pressedBtn = b.getText();

            // if the Edit button has been clicked
            if (pressedBtn.equals("Edit")) {

                textEditName.setText(textName.getText());
                textEditAge.setText(textAge.getText());
                textEditDOB.setText(textDOB.getText());

                textEditName.setEnabled(true);
                textEditAge.setEnabled(true);
                textEditDOB.setEnabled(true);

                saveBtn.setEnabled(true);
                cancelBtn.setEnabled(true);

            } else if (pressedBtn.equals("Save")) { // if the Save button has been clicked

                int reply = JOptionPane.showConfirmDialog(null, "Are you sure you want to save?", "Save", JOptionPane.YES_NO_OPTION);

                if (reply == JOptionPane.YES_OPTION) {

                    updateXML();
                }

            } else { // else the Cancel button has been clicked

                nullEdit();
            }
        }
    }

    public void updateXML(){

        // for each user in the node list, find an ID match
        for (int i = 0; i < listOfUsers.getLength(); i++) {

            Element el = (Element) listOfUsers.item(i);
            String strId = el.getAttribute("id");

            // if an ID match has been found, update the component's details
            if (objID.equals(strId)) {

                try {

                    String strName = textEditName.getText();
                    String strAge = textEditAge.getText();
                    String strDOB = textEditDOB.getText();

                    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
                    Document doc = docBuilder.parse(new File(fileSource));

                    doc.getElementsByTagName("name").item(i).setTextContent(strName);
                    doc.getElementsByTagName("age").item(i).setTextContent(strAge);
                    doc.getElementsByTagName("dob").item(i).setTextContent(strDOB);

                    TransformerFactory transformerFactory = TransformerFactory.newInstance();
                    Transformer transformer = transformerFactory.newTransformer();
                    DOMSource domSource = new DOMSource(doc);
                    StreamResult streamResult = new StreamResult(new File(fileSource));

                    transformer.transform(domSource, streamResult);

                    el.getElementsByTagName("name").item(i).setTextContent(strName);
                    el.getElementsByTagName("age").item(i).setTextContent(strAge);
                    el.getElementsByTagName("dob").item(i).setTextContent(strDOB);

                    textName.setText(strName);
                    textAge.setText(strAge);
                    textDOB.setText(strDOB);
                    editBtn.setEnabled(true);

                    break;

                } catch (Exception e) {

                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                DomainModel dm = new DomainModel();
                dm.setVisible(true);
            }
        });
    }
}

I am now implementing some additional features, and I was insisted to separate the DOM from "persistence layer". I have tried researching further into this, however I'm still a bit vague on what to do or what it is.

Many thanks.

Was it helpful?

Solution 2

Thanks to Kamil Mikolajczyk, I was able to research MVC with Java and found a pretty nice example via this link.

Again, thank you for your help Kamil Mikolajczyk.

OTHER TIPS

I'm switching from comments to answers, because I need formatting here ;)

first of all, this createTree method should be split into smaller parts, because it actually mixes all layers. Controller shouldn't care what UI controls you have, and it shouldn't care what kind of data store it's using. Imagine a pseudecode like this:

interface DataStore { // model
    List<User> getUsers();
    void saveNewUser(User user);
}
class XmlDataStoreImpl implements DataStore { ... }
interface Ui { // view
    void showUsers(List<User> users);
    User getUserDataFromControls();
}
class DomainModel extends JFrame implements Ui { // view
    static void main(String[] args) {
        DataStore dataStore = new XmlDataStoreImpl("users.xml");
        AppController app = new AppController(dataStore, this);
        app.loadUsers();
    }
    void init() {
        createControls(); // create empty JTree object and other controlls
    }
}
class AppController { // controller
    DataStore dataStore;
    Ui ui;
    public AppController(DataStore ds, Ui ui) { 
        ... 
        ui.init();
    }
    void loadUsers() {
        ui.showUsers(dataStore.getUsers()); // this line is your "createTree" but independent on implementations of model and view
    }
    void saveButtonClickedHandler() {
        User user = ui.getUserDataFromControls();
        dataStore.saveNewUser(user);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top