All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.purl.sword.client.ServicePanel Maven / Gradle / Ivy

The newest version!
/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */

/**
 * Copyright (c) 2007, Aberystwyth University
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 *  - Neither the name of the Centre for Advanced Software and
 *    Intelligent Systems (CASIS) nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
package org.purl.sword.client;

import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import org.purl.sword.atom.Author;
import org.purl.sword.atom.Content;
import org.purl.sword.atom.Contributor;
import org.purl.sword.atom.Generator;
import org.purl.sword.atom.Link;
import org.purl.sword.atom.TextConstruct;
import org.purl.sword.base.Collection;
import org.purl.sword.base.DepositResponse;
import org.purl.sword.base.SWORDEntry;
import org.purl.sword.base.Service;
import org.purl.sword.base.ServiceDocument;
import org.purl.sword.base.SwordAcceptPackaging;
import org.purl.sword.base.Workspace;

/**
 * The main panel for the GUI client. This contains the top-two sub-panels: the
 * tree and the text area to show the details of the selected node.
 *
 * @author Neil Taylor
 */
public class ServicePanel extends JPanel
    implements TreeSelectionListener {
    /**
     * The top level item in the tree that lists services.
     */
    DefaultMutableTreeNode top;

    /**
     * The tree model used to display the items.
     */
    DefaultTreeModel treeModel = null;

    /**
     * Tree that holds the list of services.
     */
    private JTree services;

    /**
     * The panel that shows an HTML table with any details for the selected
     * node in the services tree.
     */
    private JEditorPane details;

    /**
     * A registered listener. This listener will be notified when there is a
     * different node selected in the service tree.
     */
    private ServiceSelectedListener listener;

    /**
     * Create a new instance of the panel.
     */
    public ServicePanel() {
        super();
        setLayout(new BorderLayout());

        top = new DefaultMutableTreeNode("Services & Posted Files");
        treeModel = new DefaultTreeModel(top);

        services = new JTree(treeModel);
        services.setCellRenderer(new ServicePostTreeRenderer());

        JScrollPane servicesPane = new JScrollPane(services,
                                                   JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                                                   JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        details = new JEditorPane("text/html",
                                  "

Details

This panel will show the details for the currently " + "selected item in the tree.

"); JScrollPane detailsPane = new JScrollPane(details, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, servicesPane, detailsPane); splitPane.setOneTouchExpandable(true); splitPane.setResizeWeight(0.5); splitPane.setDividerLocation(200); services.addTreeSelectionListener(this); ToolTipManager.sharedInstance().registerComponent(services); add(splitPane, BorderLayout.CENTER); } /** * Renderer that displays the icons for the tree nodes. * * @author Neil Taylor */ static class ServicePostTreeRenderer extends DefaultTreeCellRenderer { Icon workspaceIcon; Icon serviceIcon; Icon collectionIcon; Icon fileIcon; /** * Initialise the renderer. Load the icons. */ public ServicePostTreeRenderer() { ClassLoader loader = this.getClass().getClassLoader(); workspaceIcon = new ImageIcon(loader.getResource("images/WorkspaceNodeImage.gif")); serviceIcon = new ImageIcon(loader.getResource("images/ServiceNodeImage.gif")); collectionIcon = new ImageIcon(loader.getResource("images/CollectionNodeImage.gif")); fileIcon = new ImageIcon(loader.getResource("images/ServiceNodeImage.gif")); } /** * Return the cell renderer. This will be the default tree cell renderer * with a different icon depending upon the type of data in the node. * * @param tree The JTree control. * @param value The value to display. * @param sel True if the node is selected. * @param expanded True if the node is expanded. * @param leaf True if the node is a leaf. * @param row The row. * @param hasFocus True if the node has focus. */ public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { JComponent comp = (JComponent) super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus); DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; Object o = node.getUserObject(); if (o instanceof TreeNodeWrapper) { TreeNodeWrapper wrapper = (TreeNodeWrapper) o; comp.setToolTipText(wrapper.toString()); Object data = wrapper.getData(); if (data instanceof Service) { setIcon(serviceIcon); } else if (data instanceof Workspace) { setIcon(workspaceIcon); } else if (data instanceof Collection) { setIcon(collectionIcon); } else if (data instanceof SWORDEntry) { setIcon(fileIcon); } } else { comp.setToolTipText(null); } return comp; } } /** * Set the service selected listener. This listener will be notified when * there is a selection change in the tree. * * @param listener The listener. */ public void setServiceSelectedListener(ServiceSelectedListener listener) { this.listener = listener; } /** * Process the specified service document. Add the details as a new child of the * root of the tree. * * @param url The url used to access the service document. * @param doc The service document. */ public void processServiceDocument(String url, ServiceDocument doc) { TreeNodeWrapper wrapper = null; Service service = doc.getService(); wrapper = new TreeNodeWrapper(url, service); DefaultMutableTreeNode serviceNode = new DefaultMutableTreeNode(wrapper); treeModel.insertNodeInto(serviceNode, top, top.getChildCount()); services.scrollPathToVisible(new TreePath(serviceNode.getPath())); // process the workspaces DefaultMutableTreeNode workspaceNode = null; Iterator workspaces = service.getWorkspaces(); for (; workspaces.hasNext(); ) { Workspace workspace = workspaces.next(); wrapper = new TreeNodeWrapper(workspace.getTitle(), workspace); workspaceNode = new DefaultMutableTreeNode(wrapper); treeModel.insertNodeInto(workspaceNode, serviceNode, serviceNode.getChildCount()); services.scrollPathToVisible(new TreePath(workspaceNode.getPath())); DefaultMutableTreeNode collectionNode = null; Iterator collections = workspace.collectionIterator(); for (; collections.hasNext(); ) { Collection collection = collections.next(); wrapper = new TreeNodeWrapper(collection.getTitle(), collection); collectionNode = new DefaultMutableTreeNode(wrapper); treeModel.insertNodeInto(collectionNode, workspaceNode, workspaceNode.getChildCount()); services.scrollPathToVisible(new TreePath(collectionNode.getPath())); } } // for } /** * Holds the data for a tree node. It specifies the name that will be displayed * in the node, and stores associated data. * * @author Neil Taylor */ static class TreeNodeWrapper { /** * The node name. */ private String name; /** * The user data. */ private Object userObject; /** * Create a new instance. * * @param name The name of the node. * @param data The data in the node. */ public TreeNodeWrapper(String name, Object data) { this.name = name; this.userObject = data; } /** * Retrieve the data that is stored in this node. * * @return The data. */ public Object getData() { return userObject; } /** * Get a string description for this node. */ public String toString() { if (name == null || name.trim().equals("")) { return "Unspecified"; } return name; } } /** * Respond to a changed tree selection event. Update the details panel to * show an appropriate message for the newly selected node. Also, * alert the selection listener for this panel. The listener will receive * a path, if a collection has been selected. Otherwise, the listener * will receive null. */ public void valueChanged(TreeSelectionEvent evt) { // Get all nodes whose selection status has changed TreePath[] paths = evt.getPaths(); for (int i = 0; i < paths.length; i++) { if (evt.isAddedPath(i)) { // process new selections DefaultMutableTreeNode node; node = (DefaultMutableTreeNode) (paths[i].getLastPathComponent()); Object o = node.getUserObject(); if (o instanceof TreeNodeWrapper) { try { TreeNodeWrapper wrapper = (TreeNodeWrapper) o; Object data = wrapper.getData(); if (data instanceof Service) { showService((Service) data); alertListener(null); } else if (data instanceof Workspace) { showWorkspace((Workspace) data); if (listener != null) { alertListener(null); } } else if (data instanceof Collection) { Collection c = (Collection) data; showCollection(c); alertListener(c.getLocation()); } else if (data instanceof SWORDEntry) { showEntry((SWORDEntry) data); alertListener(null); } else { details.setText("unknown"); alertListener(null); } } catch (Exception e) { details.setText( "An error occurred. The message was: " + e.getMessage() + ""); alertListener(null); e.printStackTrace(); } } else { details.setText("please select one of the other nodes"); alertListener(null); } } } } /** * Notify the listener that there has been a change to the currently selected * item in the tree. * * @param value The value to send to the listener. */ private void alertListener(String value) { if (listener != null) { listener.selected(value); } } /** * Add a new HTML table row to the specified StringBuffer. The label is displayed in * the left column and the value is displayed in the right column. * * @param buffer The destination string buffer. * @param label The label to add. * @param value The corresponding value to add. */ private void addTableRow(StringBuffer buffer, String label, Object value) { buffer.append(""); buffer.append(label); buffer.append(""); buffer.append(displayableValue(value)); buffer.append(""); } /** * Show the specified service data in the details panel. * * @param service The service node to display. */ private void showService(Service service) { StringBuffer buffer = new StringBuffer(); buffer.append(""); buffer.append(""); buffer.append(""); buffer.append(""); addTableRow(buffer, "SWORD Version", service.getVersion()); addTableRow(buffer, "NoOp Support ", service.isNoOp()); addTableRow(buffer, "Verbose Support ", service.isVerbose()); String maxSize = ""; // Commented out the following code as the client code is out of step with the // Sword 'base' library and wont compile. - Robin Taylor. //if ( service.maxUploadIsDefined() ) //{ // maxSize = "" + service.getMaxUploadSize() + "kB"; //} //else //{ maxSize = "undefined"; //} addTableRow(buffer, "Max File Upload Size ", maxSize); buffer.append("
Service Summary
"); buffer.append(""); buffer.append(""); details.setText(buffer.toString()); } /** * Display the workspace data in the details panel. * * @param workspace The workspace. */ private void showWorkspace(Workspace workspace) { StringBuffer buffer = new StringBuffer(); buffer.append(""); buffer.append(""); buffer.append(""); buffer .append(""); addTableRow(buffer, "Workspace Title", workspace.getTitle()); buffer.append("
Workspace Summary
"); buffer.append(""); buffer.append(""); details.setText(buffer.toString()); } /** * Return the parameter unmodified if set, or the not defined text if null * @param s * @return s or ClientConstants.NOT_DEFINED_TEXT */ private Object displayableValue(Object s) { if (null == s) { return ClientConstants.NOT_DEFINED_TEXT; } else { return s; } } /** * Add a string within paragraph tags. * * @param buffer The buffer to add the message to. * @param message The message to add. */ private void addPara(StringBuffer buffer, String message) { buffer.append("

" + message + "

"); } /** * Show the specified collection data in the details panel. * * @param collection The collection data. */ private void showCollection(Collection collection) { StringBuffer buffer = new StringBuffer(); buffer.append(""); buffer.append(""); if (collection == null) { addPara(buffer, "Invalid Collection object. Unable to display details."); } else { buffer.append(""); buffer.append( ""); addTableRow(buffer, "Collection location", collection.getLocation()); addTableRow(buffer, "Collection title", collection.getTitle()); addTableRow(buffer, "Abstract", collection.getAbstract()); addTableRow(buffer, "Collection Policy", collection.getCollectionPolicy()); addTableRow(buffer, "Treatment", collection.getTreatment()); addTableRow(buffer, "Mediation", collection.getMediation()); addTableRow(buffer, "Nested Service Document", collection.getService()); String[] accepts = collection.getAccepts(); StringBuilder acceptList = new StringBuilder(); if (accepts != null && accepts.length == 0) { acceptList.append("None specified"); } else { for (String s : accepts) { acceptList.append(s).append("
"); } } addTableRow(buffer, "Accepts", acceptList.toString()); List acceptsPackaging = collection.getAcceptPackaging(); StringBuilder acceptPackagingList = new StringBuilder(); for (Iterator i = acceptsPackaging.iterator(); i.hasNext(); ) { SwordAcceptPackaging accept = (SwordAcceptPackaging) i.next(); acceptPackagingList.append(accept.getContent()).append(" (").append(accept.getQualityValue()) .append(")"); // add a , separator if there are any more items in the list if (i.hasNext()) { acceptPackagingList.append(", "); } } addTableRow(buffer, "Accepts Packaging", acceptPackagingList.toString()); buffer.append("
Collection Summary
"); } buffer.append(""); buffer.append(""); details.setText(buffer.toString()); } /** * Display the contents of a Post entry in the display panel. * * @param entry The entry to display. */ private void showEntry(SWORDEntry entry) { StringBuffer buffer = new StringBuffer(); buffer.append(""); buffer.append(""); if (entry == null) { addPara(buffer, "Invalid Entry object. Unable to display details."); } else { buffer.append(""); buffer .append(""); // process atom:title String titleString = getTextConstructDetails(entry.getSummary()); addTableRow(buffer, "Title", titleString); // process id addTableRow(buffer, "ID", entry.getId()); // process updated addTableRow(buffer, "Date Updated", entry.getUpdated()); String authorString = getAuthorDetails(entry.getAuthors()); addTableRow(buffer, "Authors", authorString); // process summary String summaryString = getTextConstructDetails(entry.getSummary()); addTableRow(buffer, "Summary", summaryString); // process content Content content = entry.getContent(); String contentString = ""; if (content == null) { contentString = "Not defined."; } else { contentString += "Source: '" + content.getSource() + "', Type: '" + content.getType() + "'"; } addTableRow(buffer, "Content", contentString); // process links Iterator links = entry.getLinks(); StringBuffer linkBuffer = new StringBuffer(); for (; links.hasNext(); ) { Link link = links.next(); linkBuffer.append("href: '"); linkBuffer.append(link.getHref()); linkBuffer.append("', href lang: '"); linkBuffer.append(link.getHreflang()); linkBuffer.append("', rel: '"); linkBuffer.append(link.getRel()); linkBuffer.append("')
"); } if (linkBuffer.length() == 0) { linkBuffer.append("Not defined"); } addTableRow(buffer, "Links", linkBuffer.toString()); // process contributors String contributorString = getContributorDetails(entry.getContributors()); addTableRow(buffer, "Contributors", contributorString); // process source String sourceString = ""; Generator generator = entry.getGenerator(); if (generator != null) { sourceString += "Content: '" + generator.getContent() + "'
'"; sourceString += "Version: '" + generator.getVersion() + "'
'"; sourceString += "Uri: '" + generator.getUri() + "'"; } else { sourceString += "No generator defined."; } addTableRow(buffer, "Generator", sourceString); // process treatment addTableRow(buffer, "Treatment", entry.getTreatment()); // process verboseDescription addTableRow(buffer, "Verbose Description", entry.getVerboseDescription()); // process noOp addTableRow(buffer, "NoOp", entry.isNoOp()); // process formatNamespace addTableRow(buffer, "Packaging", entry.getPackaging()); // process userAgent addTableRow(buffer, "User Agent", entry.getUserAgent()); buffer.append("
Entry Summary
"); } buffer.append(""); buffer.append(""); details.setText(buffer.toString()); } /** * Retrieve the details for a TextConstruct object. * * @param data The text construct object to display. * * @return Either 'Not defined' if the data is null, or * details of the text content element. */ private String getTextConstructDetails(TextConstruct data) { String summaryStr = ""; if (data == null) { summaryStr = "Not defined"; } else { summaryStr = "Content: '" + data.getContent() + "', Type: "; if (data.getType() != null) { summaryStr += "'" + data.getType().toString() + "'"; } else { summaryStr += "undefined."; } } return summaryStr; } /** * Get the author details and insert them into a string. * * @param authors the list of authors to process. * * @return A string containing the list of authors. */ private String getAuthorDetails(Iterator authors) { // process author StringBuffer authorBuffer = new StringBuffer(); for (; authors.hasNext(); ) { Author a = authors.next(); authorBuffer.append(getAuthorDetails(a)); } if (authorBuffer.length() == 0) { authorBuffer.append("Not defined"); } return authorBuffer.toString(); } /** * Get the contributor details and insert them into a string. * * @param contributors The contributors. * * @return The string that lists the details of the contributors. */ private String getContributorDetails(Iterator contributors) { // process author StringBuffer authorBuffer = new StringBuffer(); for (; contributors.hasNext(); ) { Contributor c = contributors.next(); authorBuffer.append(getAuthorDetails(c)); } if (authorBuffer.length() == 0) { authorBuffer.append("Not defined"); } return authorBuffer.toString(); } /** * Build a string that describes the specified author. * * @param author The author. * * @return The string description. */ private String getAuthorDetails(Author author) { // process author StringBuffer authorBuffer = new StringBuffer(); authorBuffer.append(author.getName()); authorBuffer.append(" (email: '"); authorBuffer.append(author.getEmail()); authorBuffer.append("', uri: '"); authorBuffer.append(author.getUri()); authorBuffer.append("')
"); return authorBuffer.toString(); } /** * Process the deposit response and insert the details into the tree. If the url * matches one of the collections in the tree, the deposit is added as a child * node. Otherwise, the node is added as a child of the root. * * @param url The url of the collection that the file was posted to. * * @param response The details of the deposit. */ public void processDepositResponse(String url, DepositResponse response) { SWORDEntry entry = response.getEntry(); Object title = entry.getTitle(); if (title == null) { title = "Undefined"; } else { title = entry.getTitle().getContent(); } TreeNodeWrapper wrapper = new TreeNodeWrapper(title.toString(), entry); DefaultMutableTreeNode entryNode = new DefaultMutableTreeNode(wrapper); DefaultMutableTreeNode newParentNode = top; List nodes = getCollectionNodes(); for (DefaultMutableTreeNode node : nodes) { Object o = node.getUserObject(); if (o instanceof TreeNodeWrapper) { TreeNodeWrapper collectionWrapper = (TreeNodeWrapper) o; Object data = collectionWrapper.getData(); if (data instanceof Collection) { Collection col = (Collection) data; String location = col.getLocation(); if (location != null && location.equals(url)) { newParentNode = node; break; } } } } treeModel.insertNodeInto(entryNode, newParentNode, newParentNode.getChildCount()); services.scrollPathToVisible(new TreePath(entryNode.getPath())); } /** * Get a list of all current collections displayed in the tree. * * @return An array of the URLs for the collections. */ public String[] getCollectionLocations() { List nodes = getCollectionNodes(); String[] locations = new String[nodes.size()]; DefaultMutableTreeNode node; for (int i = 0; i < nodes.size(); i++) { node = nodes.get(i); Object o = node.getUserObject(); if (o instanceof TreeNodeWrapper) { TreeNodeWrapper collectionWrapper = (TreeNodeWrapper) o; Object data = collectionWrapper.getData(); if (data instanceof Collection) { Collection col = (Collection) data; String location = col.getLocation(); if (location != null) { locations[i] = location; } } } } return locations; } /** * Get a list of nodes that contain collections. * * @return A vector of the collection nodes. */ private List getCollectionNodes() { List nodes = new ArrayList(); DefaultMutableTreeNode node; Enumeration treeNodes = top.depthFirstEnumeration(); while (treeNodes.hasMoreElements()) { node = (DefaultMutableTreeNode) treeNodes.nextElement(); Object o = node.getUserObject(); if (o instanceof TreeNodeWrapper) { TreeNodeWrapper wrapper = (TreeNodeWrapper) o; Object data = wrapper.getData(); if (data instanceof Collection) { nodes.add(node); } } } return nodes; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy