001    /**
002     * iFish - An iRiver iHP jukebox database creation tool
003     *
004     * Copyright (C) 2009 Richard "Shred" Körber
005     *   http://ifish.shredzone.org
006     *
007     * This program is free software: you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published by
009     * the Free Software Foundation, either version 3 of the License, or
010     * (at your option) any later version.
011     *
012     * This program is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
019     */
020    package net.shredzone.ifish.db;
021    
022    import net.shredzone.ifish.ltr.*;
023    import java.io.*;
024    
025    /**
026     * This class represents an Entry which was read from the file system.
027     *
028     * @author    Richard Körber &lt;dev@shredzone.de&gt;
029     * @version   $Id: FileEntry.java 291 2009-04-28 21:29:27Z shred $
030     */
031    public class FileEntry extends Entry implements Serializable {
032      private static final long serialVersionUID = 3905246710342039350L;
033    
034      private final File base;
035      private final File file;
036      private final String title;
037      private final String artist;
038      private final String album;
039      private final String genre;
040      private final String comment;
041      
042      /**
043       * Create a new entry from a file. An exception is thrown if the
044       * directory or file name lengths will exceed the limit set by the
045       * iHP database. You can use isFileNameFitting() and isDirNameFitting()
046       * to pre-examine if the lenghts would be exceeded.
047       * <p>
048       * A LTR instance will automatically be created about the file here.
049       *
050       * @param   base        Base directory (the jukebox mount point)
051       * @param   file        File name to create an Entry for
052       * @param   factory     LTRFactory to be used
053       */
054      public FileEntry( File base, File file, LTRFactory factory )
055      throws IOException, DatabaseException {
056        this( base, file, factory.create( file ) );
057      }
058    
059      /**
060       * Create a new entry from a file. An exception is thrown if the
061       * directory or file name lengths will exceed the limit set by the
062       * iHP database. You can use isFileNameFitting() and isDirNameFitting()
063       * to pre-examine if the lenghts would be exceeded.
064       * <p>
065       * A LTR object must be passed that describes the music tag. An exception
066       * will be thrown if ltr is null.
067       *
068       * @param   base        Base directory (the jukebox mount point)
069       * @param   file        File name to create an Entry for
070       * @param   ltr         LTR about the file contents
071       */
072      public FileEntry( File base, File file, LTR ltr )
073      throws IOException, DatabaseException {
074        if( ltr==null ) {
075          throw new IllegalArgumentException( "no tag was found" );
076        }
077    
078        this.base = base;
079        this.file = file;
080        
081        //--- Check file name length ---
082        if( !FileEntry.isFileNameFitting( base, file ) ) {
083          throw new DatabaseException( "illegal file name: "+file );
084        }
085        
086        //--- Check directory length ---
087        if( !FileEntry.isDirNameFitting( base, file ) ) {
088          throw new DatabaseException( "illegal path name: "+file );
089        }
090        
091        //--- Store the data ---
092        title   = ltr.getTitle();
093        artist  = ltr.getArtist();
094        album   = ltr.getAlbum();
095        genre   = ltr.getGenre();
096        comment = ltr.getComment();
097      }
098    
099      /**
100       * Checks if the filename part of the given file would fit into
101       * this entry. The iHP database only allows up to 52 characters for
102       * each the directory and the file part.
103       *
104       * @param   base        Base Directory
105       * @param   file        File to be checked
106       * @return  true: fits, false: won't fit.
107       */
108      public static boolean isFileNameFitting( File base, File file ) {
109        return( file.getName().length() <= 52 );
110      }
111    
112      /**
113       * Checks if the directory part of the given file would fit into
114       * this entry. The iHP database only allows up to 52 characters for
115       * each part of the directory and the file part.
116       *
117       * @param   base        Base Directory
118       * @param   file        File to be checked
119       * @return  true: fits, false: won't fit.
120       */
121      public static boolean isDirNameFitting( File base, File file ) {
122        File current = file.getParentFile();
123        while( current!=null && !current.equals(base) ) {
124          if( current.getName().length() > 52 )
125            return false;
126          current = current.getParentFile();
127        }
128        return true;
129      }
130      
131      /**
132       * Get the file behind this entry. Returns null if there is no matching
133       * file in the file system.
134       *
135       * @return    File represented by this entry
136       */
137      @Override
138      public File getFile() {
139        return file;
140      }
141    
142      /**
143       * Get the file name of this entry. This is the path and file name
144       * relative to the iHP root directory mount point, and always
145       * using wrongslashes (even on unixoid systems). 
146       *
147       * @return    File name
148       */
149      @Override
150      public String getFileName() {
151        String name = "";
152        
153        //--- Assemble file name ---
154        // Go up to the base directory, and add each path element
155        // to the filename, always using wrongslashes as separator.
156        File current = file;
157        while( current!=null && !current.equals(base) ) {
158          String cname = current.getName();
159          if(! cname.equals("") ) {
160            name = '\\' + cname + name;
161          }
162          current = current.getParentFile();
163        }
164        
165        //--- Fix double slash bug ---
166        if( name.startsWith("\\\\") ) {
167          name = name.substring(1);
168        }
169        
170        return name;
171      }
172      
173      /**
174       * Get the title of the track, as given by the file's tag. Does not
175       * return null.
176       *
177       * @return    Title
178       */
179      @Override
180      public String getTitle() {
181        return title;
182      }
183      
184      /**
185       * Get the artist of the track, as given by the file's tag. Does not
186       * return null.
187       *
188       * @return    Artist
189       */
190      @Override
191      public String getArtist() {
192        return artist;
193      }
194      
195      /**
196       * Get the album of the track, as given by the file's tag. Does not
197       * return null.
198       *
199       * @return    Album
200       */
201      @Override
202      public String getAlbum() {
203        return album; 
204      }
205      
206      /**
207       * Get the genre of the track, as given by the file's tag. This is
208       * always a word, not a number. Does not return null.
209       *
210       * @return    Genre
211       */
212      @Override
213      public String getGenre() {
214        return genre;
215      }
216     
217      /**
218       * Get the comment of the track, as given by the file's tag. Does not
219       * return null.
220       *
221       * @return    Comment
222       */
223      public String getComment() {
224        return comment;
225      }
226      
227    }
228