/* * [MaxiFD.java] * * Summary: File Descriptor, describes one file. Not for directories! We can hold whole directory tree in RAM. * * Copyright: (c) 2003-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 10.2 2009-04-03 tidy up code to check presence of necessary files to make it more WORA. * Case sensitive. Stored internally relative to a base. Replaces old FD class. Only difference is * pointer to ZD is now a * MaxiZD. */ package com.mindprod.replicatorsender; import com.mindprod.fastcat.FastCat; import com.mindprod.replicatorcommon.Config; import com.mindprod.replicatorcommon.FilenameContext; import com.mindprod.replicatorcommon.MiniFD; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.Serializable; import java.util.Comparator; /** * File Descriptor, describes one file. Not for directories! We can hold whole directory tree in RAM. * * @author Roedy Green, Canadian Mind Products * @version 10.2 2009-04-03 tidy up code to check presence of necessary files to make it more WORA. * Case sensitive. Stored internally relative to a base. Replaces old FD class. Only difference is pointer * to ZD is now a * MaxiZD. * @since 2003-08-21 */ public final class MaxiFD extends MiniFD implements Serializable, Cloneable { /** * Layout version number. */ public static final long serialVersionUID = 34L; /** * Comparator to sort by timestamp and filename. */ public static final MaxiFDByDateAndName BY_DATE_AND_FILENAME = new MaxiFDByDateAndName(); /** * Comparator to sort by filename. */ public static final MaxiFDByFilename BY_FILENAME = new MaxiFDByFilename(); /** * Which zip file this file is assigned to. Null if not assigned. */ private MaxiZD zip; /** * zip number where this file is stored. 0 means not assigned yet. */ private int zipNumber; /** * Constructor * * @param miniFD a miniFD. We will pad other fields out later. */ public MaxiFD( MiniFD miniFD ) { super( miniFD ); } /** * Constructor * * @param dir directory, usually relative to some base, without leading or trailing \ * @param filename including extension, using clockSetter dependent separators. */ public MaxiFD( String dir, String filename ) { super( dir, filename ); } /** * Set which zip file this file is stored in. Automatically calls MaxiZD.assign(MaxiFD) to build the link the other * way as well. * * @param zip Reference to corresponding Zip descriptor. If null, unassign. */ public void assignZip( @Nullable MaxiZD zip ) { if ( zip == null ) { this.zip = null; this.zipNumber = 0; } else { this.zip = zip; this.zipNumber = zip.getZipNumber(); assert zip.status == ZDStatus.A_UNCREATED : "Assignment to an existing zip"; zip.assignFile( this ); } } /** * Clone the MaxiFD object. Note you must cast the result to (MaxiFD). * * @return Shallow copy. */ @SuppressWarnings( { "CloneDoesntDeclareCloneNotSupportedException" } ) public Object clone() { try { return super.clone(); } catch ( CloneNotSupportedException e ) { return null; } } /** * a debugging string that display all the fields of MaxiFD * * @return full debug string representation of the MaxiFD */ public String dump() { final FastCat sb = new FastCat( 12 ); sb.append( "MaxiFD " ); if ( isDeleted ) { sb.append( "DELETED " ); } sb.append( "z" ); sb.append( zipNumber ); sb.append( " " ); sb.append( super.toString() ); sb.append( " fileLength:" ); sb.append( getFileLength() ); sb.append( displayTimestamps() ); if ( zip == null ) { sb.append( " no ZD" ); } else if ( zip.getZipNumber() != zipNumber ) { sb.append( " WRONG ZD!!" ); } return sb.toString(); } /** * equals uses case-insensitive definition * * @param obj Other object to compare to * * @return true if have same filenames CASE SENSITIVE */ public boolean equals( Object obj ) { return obj instanceof MaxiFD && getFilename( FilenameContext.INSIDE_ZIP ).equals( ( ( MaxiFD ) obj ).getFilename( FilenameContext.INSIDE_ZIP ) ); } /** * get the fully qualified filename : e.g. E:\mindprod\jgloss\java.html * * @param where where-code ON_SOURCE, ON_TARGET, INSIDE_ZIP format of filename you want. * * @return fully qualified name of the file. */ public String getFilename( final FilenameContext where ) { switch ( where ) { case ON_SOURCE: return ConfigForSender .SENDER_BASE_DIR + File .separatorChar + getRelativeFilename( File.separatorChar ); case ON_TARGET: case INSIDE_ZIP: default: return super.getFilename( where ); } } /** * Which zip file this file is stored in. * * @return MaxiZD of corresponding ZIP file where this file lives. null if unassigned. */ public MaxiZD getZip() { return this.zip; } /** * Which zip file number this file is stored in. * * @return zip file number */ public int getZipNumber() { return this.zipNumber; } /** * hashCode use case-insensitive definition of equals * * @return hashcode */ public int hashCode() { return getFilename( FilenameContext.INSIDE_ZIP ).hashCode(); } /** * Strip MaxiFD back to a MiniFD for use on client. * * @return MiniFD stripped down file description. */ public MiniFD strip() { return new MiniFD( this ); } /** * debugging method to dump fields as a single string. * * @return String containing various fields. */ public String toString() { final FastCat sb = new FastCat( 4 ); sb.append( getFilename( FilenameContext.ON_SOURCE ) ); sb.append( displayTimestamps() ); sb.append( " zip:" ); sb.append( zipNumber ); return sb.toString(); } /** * Sort by timestamp. *

* Defines an alternate sort order for MaxiFD. * * @version 1.0 2009-05-22 - initial release * @since 2009-05-22 */ static class MaxiFDByDateAndName implements Comparator { /** * Layout version number. */ @SuppressWarnings( { "UnusedDeclaration" } ) static final long serialVersionUID = 200L; /** * Sort by timestamp. * Defines an alternate sort order for MaxiFD. * Compare two MaxiFD Objects. * Compares timestamp then MiniFD fields then getFileLength(). * Informally, returns (a-b), or +ve if a is more positive than b. * * @param a first MaxiFD to compare * @param b second MaxiFD to compare * * @return +ve if a>b, 0 if a==b, -ve if a<b */ public final int compare( MaxiFD a, MaxiFD b ) { long diff = a.timestamp - b.timestamp; if ( diff != 0 ) { return Long.signum( diff ); } @SuppressWarnings( { "ConstantConditions" } ) int diff1 = Config.CASE_SENSITIVE ? MiniFD.comparePathCaseSensitive( a, b ) : MiniFD.comparePathIgnoreCase( a, b ); if ( diff1 != 0 ) { return diff1; } return Long.signum( a.getFileLength() - b.getFileLength() ); } } /** * Sort by filename. *

* Defines an alternate sort order for MaxiFD. * * @version 1.0 2009-05-22 - initial release * @since 2009-05-22 */ static class MaxiFDByFilename implements Comparator, Serializable { /** * Layout version number. */ static final long serialVersionUID = 200L; /** * Sort by filename. * Defines an alternate sort order for MaxiFD. * Compare two MaxiFD Objects. * Compares x. * Informally, returns (a-b), or +ve if a is more positive than b. * * @param a first MaxiFD to compare * @param b second MaxiFD to compare * * @return +ve if a>b, 0 if a==b, -ve if a<b */ public final int compare( MaxiFD a, MaxiFD b ) { //noinspection ConstantConditions return Config.CASE_SENSITIVE ? MiniFD.comparePathCaseSensitive( a, b ) : MiniFD.comparePathIgnoreCase( a, b ); } } } // end MaxiFD