⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playlistmodel.java

📁 Eclipse高级编程3源码(书本源码)
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
 * Copyright (c) 2004 Berthold Daum. All rights reserved. This program and the
 * accompanying materials are made available under the terms of the Common
 * Public License v1.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: Berthold Daum
 ******************************************************************************/
package com.bdaum.jukebox;

import java.io.*;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;

import org.apache.crimson.jaxp.DocumentBuilderFactoryImpl;
import org.apache.xalan.serialize.SerializerToXML;
import org.eclipse.jface.util.ListenerList;
import org.eclipse.jface.viewers.*;
import org.w3c.dom.*;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * This class implements the playlist domain model. XML is used as
 * file format to make the model data persistent. Access to the XML
 * data is organized via the JAXP DOM.
 */
public class PlaylistModel implements IPlaylist {

  // Name of INI file
  private final static String INIFILE = "jukebox.ini";

  // XML prolog
  private final static String XMLPROLOG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  // Empty playlist
  private final static String XMLROOT = XMLPROLOG
          + "<playlist></playlist>";
  // Tag for playlist entries
  public final static String RECORD = "record";

  // INI file
  private File iniFile;
  // current playlist file name
  private String currentPlaylistFile;
  // current playlist DOM
  private Document playlistDoc;
  // current playlist entry DOM node
  private Node currentElement;
  // Listeners to be informed about changes
  private ListenerList selectionChangedListeners = new ListenerList();

  /**
   * Constructor for PlaylistModel.
   */
  public PlaylistModel() {
    super();
    try {
      // Try to read the INI file
      iniFile = new File(INIFILE);
      InputStream stream = new FileInputStream(iniFile);
      byte[] buffer = new byte[1024];
      int l = stream.read(buffer);
      // If it exists, read the name of the most recent
      // playlist and open this playlist
      openPlaylist(new String(buffer, 0, l));

    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    }
  }

  /**
   * Opens the playlist file
   * 
   * @param name
   *        Name of playlist file
   */
  private void openPlaylist(
    String name) {
    if (name == null) return;
    currentPlaylistFile = name;
    File playlistFile = new File(name);
    // Input stream of playlist file
    InputStream stream;
    try {
      stream = new FileInputStream(playlistFile);
    } catch (FileNotFoundException e) {
      // File does not exist
      // We create an empty playlist document
      stream = makeStream(XMLROOT);
    }
    if (stream != null) try {
      // We parse the file content, creating a DOM
      playlistDoc = parseStream(stream, false);
    } catch (Throwable e) {
      playlistDoc = null;
      System.err.println("XML parsing error: " + e);
    }
    if (playlistDoc != null) {
      // We look for <record>-elements and set the first one
      // as current song
      NodeList nl = playlistDoc.getElementsByTagName(RECORD);
      if (nl.getLength() > 0) currentElement = nl.item(0);
    }
  }

  /**
   * Convert string into InputStream
   * 
   * @param input -
   *        Input string
   * @return InputStream - resulting InputStream instance
   */
  public static InputStream makeStream(
    String input) {
    try {
      return new ByteArrayInputStream(input.getBytes("UTF8"));
    } catch (UnsupportedEncodingException x) {
      // should never happen
      return null;
    }
  }

  /**
   * Convert serialized XML stream into DOM tree.
   * 
   * @param stream -
   *        input stream
   * @param silent -
   *        don't show error messages on the console if set to true
   * @return Document - the resulting DOM document
   * @throws Throwable -
   *         various Throwables from Parser
   */
  private static Document parseStream(
    InputStream stream, boolean silent) throws Throwable {
    // Create InputSource from stream
    InputSource source = new InputSource(stream);
    // Create a document builder factory
    DocumentBuilderFactory factory = new DocumentBuilderFactoryImpl();
    // Create a document builder
    DocumentBuilder builder = factory.newDocumentBuilder();
    // When "silent" is set we override the SAX error handler and
    // suppress the output of error message to the Java console.
    if (silent) {
      builder.setErrorHandler(new ErrorHandler() {
        public void error(
          SAXParseException exception) throws SAXException {
          throw exception;
        }

        public void fatalError(
          SAXParseException exception) throws SAXException {
          throw exception;
        }

        public void warning(
          SAXParseException exception) throws SAXException {
          throw exception;
        }
      });
    }
    // Everything is configured - let's parse.
    return builder.parse(source);
  }

  /**
   * Save current playlist to file.
   */
  private void savePlaylist() {
    if (playlistDoc == null || currentPlaylistFile == null)
      return;
    File playlistFile = new File(currentPlaylistFile);
    try {
      // Create new file and set output stream to this file.
      playlistFile.createNewFile();
      OutputStream stream = new FileOutputStream(playlistFile);
      // Serialize DOM and write to output stream
      stream.write(serializeNode(playlistDoc, true)
              .toByteArray());
    } catch (IOException e) {
      System.err.println("IO-exception during save: " + e);
    }
  }

  /**
   * Convert whole DOM document or subtree into XML stream.
   * 
   * @param nod -
   *        DOM document or DOM node
   * @param prolog -
   *        "true" if an XML prolog is required
   * @return ByteArrayOutputStream - serialized XML text
   */
  public static ByteArrayOutputStream serializeNode(
    Node nod, boolean prolog) {
    // Set output formats
    // (no identation, XML prolog depending on option)
    SerializerToXML serializer = new SerializerToXML();
    Properties props = new Properties();
    props.setProperty(OutputKeys.METHOD, "xml");
    props.setProperty(OutputKeys.INDENT, "no");
    props.setProperty(OutputKeys.OMIT_XML_DECLARATION,
            (prolog) ? "no" : "yes");
    serializer.setOutputFormat(props);
    // Create OutputStream and Serializer instances.
    ByteArrayOutputStream outstream = new ByteArrayOutputStream();
    serializer.setOutputStream(outstream);
    try {
      // Serialize.
      serializer.serialize(nod);
    } catch (IOException e) { // should never happen
    }
    return outstream;
  }

  /** *** IPlayList methods **** */

  /**
   * @see IPlayList#getPlaylistName()
   */
  public String getPlaylistName() {
    return currentPlaylistFile;
  }

  /**
   * @see IPlayList#next()
   */
  public boolean next() {
    // fetch next entry
    Node nod = getNext();
    if (nod == null) return false;
    // in case of success set current entry to this value
    setCurrent(nod);
    return true;
  }

  /**
   * Searches from current entry onwards for next entry.
   * 
   * @return Node - the next entry
   */
  private Node getNext() {
    Node nod = currentElement;
    // search next element with tag <record>
    while (nod != null) {
      nod = nod.getNextSibling();
      if (nod instanceof Element
              && ((Element) nod).getTagName().equals(RECORD))
        return nod;
    }
    return null;
  }

  /**
   * @see IPlayList#previous()
   */
  public boolean previous() {
    // fetch previous entry
    Node nod = getPrevious();
    if (nod == null) return false;
    // in case of success set current entry to this value
    setCurrent(nod);
    return true;
  }

  /**
   * Searches from current entry onwards for previous entry.
   * 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -