2006-12-19 09:29:57 +00:00

678 lines
14 KiB
Java

/*
* Copyright (C) 2006 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.filesys.avm;
import org.alfresco.filesys.server.filesys.FileName;
/**
* AVM Path Class
*
* <p>Parses a share relative path into store, version and remaining path values.
*
* @author gkspencer
*/
public class AVMPath {
// Constants
//
// Invalid version id value
private static final int InvalidVersionId = -2;
// Version id string for the head version
public static final String VersionNameHead = "HEAD";
// Folder name for the versions folder
public static final String VersionsFolder = "VERSION";
// Head and version sub-folders
public static final String DataFolder = "DATA";
public static final String MetaDataFolder = "METADATA";
// Version folder prefix
public static final String VersionFolderPrefix = "v";
// AVM path seperator
public static final char AVM_SEPERATOR = '/';
public static final String AVM_SEPERATOR_STR = "/";
// Level identifiers
public enum LevelId { Invalid, Root, StoreRoot, Head, HeadData, HeadMetaData, VersionRoot, Version, VersionData, VersionMetaData, StorePath };
// Level identifier for this path
private LevelId m_levelId = LevelId.Invalid;
// Store name
private String m_storeName;
// Version id
private int m_version = InvalidVersionId;
// Remaining path
private String m_path;
// AVM style path
private String m_avmPath;
/**
* Default constructor
*/
public AVMPath()
{
}
/**
* Class constructor
*
* <p>Construct an AVM path for the virtualization view, with store and version folders
*
* @param shrPath String
*/
public AVMPath(String shrPath)
{
// Parse the path
parsePath( shrPath);
}
/**
* Class constructor
*
* <p>Construct an AVM path for a standard view onto a store/version
*
* @param storeName String
* @param version int
* @param path String
*/
public AVMPath(String storeName, int version, String path)
{
// Parse the path
parsePath( storeName, version, path);
}
/**
* Return the level id for the path
*
* @return LevelId
*/
public LevelId isLevel()
{
return m_levelId;
}
/**
* Return the store name
*
* @return String
*/
public final String getStoreName()
{
return m_storeName;
}
/**
* Check if the version id was specified in the path
*
* @return boolean
*/
public final boolean hasVersion()
{
return m_version != InvalidVersionId ? true : false;
}
/**
* Return the version id
*
* @return int
*/
public final int getVersion()
{
return m_version;
}
/**
* Return the version as a string
*
* @return String
*/
public final String getVersionString()
{
if ( m_version == -1)
return VersionNameHead;
return "" + m_version;
}
/**
* Check if there is a share relative path
*
* @return boolean
*/
public final boolean hasRelativePath()
{
return m_path != null ? true : false;
}
/**
* Return the share relative path
*
* @return String
*/
public final String getRelativePath()
{
return m_path;
}
/**
* Return the AVM style path, in <store>:/<path> format
*
* @return String
*/
public final String getAVMPath()
{
return m_avmPath;
}
/**
* Check if the path is valid
*
* @return boolean
*/
public final boolean isValid()
{
return m_levelId == LevelId.Invalid ? false : true;
}
/**
* Check if the path is to a pseudo folder in the virtualization view
*
* @return boolean
*/
public final boolean isPseudoPath()
{
return m_levelId == LevelId.Invalid || m_levelId == LevelId.StorePath ? false : true;
}
/**
* Check if hte path is a read-only part of the pseudo folder tree
*
* @return boolean
*/
public final boolean isReadOnlyPseudoPath()
{
if ( isLevel() == LevelId.Root || isLevel() == LevelId.StoreRoot || isLevel() == LevelId.VersionRoot ||
isLevel() == LevelId.Head || isLevel() == LevelId.Version)
return true;
return false;
}
/**
* Check if the path is the root path
*
* @return boolean
*/
public final boolean isRootPath()
{
return m_levelId == LevelId.Root ? true : false;
}
/**
* Parse the path, for the virtualization view onto all stores/versions
*
* @param path String
*/
public final void parsePath( String path)
{
// Clear current settings
m_storeName = null;
m_version = InvalidVersionId;
m_path = null;
m_avmPath = null;
// Split the path
String[] paths = FileName.splitAllPaths(path);
if ( paths == null || paths.length == 0)
{
m_path = FileName.DOS_SEPERATOR_STR;
m_levelId = LevelId.Root;
return;
}
// Set the store name
m_storeName = paths[0];
m_levelId = LevelId.StoreRoot;
if ( paths.length > 1)
{
// Validate the next element, should be either the HEAD or VERSIONS folder
String levelStr = paths[1];
if ( levelStr.equalsIgnoreCase( VersionNameHead))
{
m_version = -1;
m_levelId = LevelId.Head;
}
else if ( levelStr.equalsIgnoreCase( VersionsFolder))
{
m_levelId = LevelId.VersionRoot;
}
else
{
// Invalid folder at the current level
m_levelId = LevelId.Invalid;
return;
}
// Check the next level, if available
if ( paths.length > 2)
{
// If the previous level is the versions root then the next level should be a
// version id folder
String folderName = paths[2];
int pathIdx = 3;
if ( isLevel() == LevelId.VersionRoot)
{
// Check that the folder name starts with the version folder prefix
if ( folderName != null && folderName.startsWith( VersionFolderPrefix) &&
folderName.length() > VersionFolderPrefix.length())
{
try
{
// Parse the version id
m_version = Integer.parseInt( folderName.substring( VersionFolderPrefix.length()));
m_levelId = LevelId.Version;
// Validate the version id
if ( m_version < -1)
{
// Invalid version id
m_levelId = LevelId.Invalid;
return;
}
}
catch ( NumberFormatException ex)
{
m_levelId = LevelId.Invalid;
return;
}
// Check for the next level
if ( paths.length > 3)
{
// Get the next level name
folderName = paths[3];
pathIdx++;
// Check for the data folder
if ( folderName.equalsIgnoreCase( DataFolder))
{
m_levelId = LevelId.VersionData;
// Set the path to the root of the store
m_path = FileName.DOS_SEPERATOR_STR;
}
else if ( folderName.equalsIgnoreCase( MetaDataFolder))
{
m_levelId = LevelId.VersionMetaData;
// Set the path to the root of the metadata
m_path = FileName.DOS_SEPERATOR_STR;
}
else
{
m_levelId = LevelId.Invalid;
return;
}
}
}
else
{
m_levelId = LevelId.Invalid;
return;
}
}
// If the previous level is head the next level should be the data or metadata folder
else if ( isLevel() == LevelId.Head)
{
// Check for the data folder
if ( folderName.equalsIgnoreCase( DataFolder))
{
m_levelId = LevelId.HeadData;
// Set the path to the root of the store
m_path = FileName.DOS_SEPERATOR_STR;
}
else if ( folderName.equalsIgnoreCase( MetaDataFolder))
{
m_levelId = LevelId.HeadMetaData;
// Set the path to the root of the metadata
m_path = FileName.DOS_SEPERATOR_STR;
}
else
{
m_levelId = LevelId.Invalid;
return;
}
}
// If there are remaining paths then build a relative path
if ( paths.length > pathIdx)
{
StringBuilder pathStr = new StringBuilder();
for ( int i = pathIdx; i < paths.length; i++)
{
pathStr.append( FileName.DOS_SEPERATOR);
pathStr.append( paths[i]);
}
m_path = pathStr.toString();
// Set the level to indicate a store relative path
m_levelId = LevelId.StorePath;
}
// Build the AVM path, in <store>:/<path> format
if ( m_path != null)
{
StringBuilder pathStr = new StringBuilder();
pathStr.append( m_storeName);
pathStr.append( ":");
pathStr.append( m_path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR));
m_avmPath = pathStr.toString();
}
}
}
}
/**
* Parse the path, to generate a path for a single store/version
*
* @param storeName String
* @param version int
* @param path String
*/
public final void parsePath( String storeName, int version, String path)
{
// Clear current settings
m_levelId = LevelId.Invalid;
m_storeName = null;
m_version = InvalidVersionId;
m_path = null;
m_avmPath = null;
// Set the store/version
m_storeName = storeName;
m_version = version;
// Save the relative path
m_path = path;
// Build the store path
StringBuilder avmPath = new StringBuilder();
avmPath.append( m_storeName);
if ( storeName.indexOf( ":") == -1)
avmPath.append( ":");
if ( path == null || path.length() == 0)
{
avmPath.append( AVM_SEPERATOR);
// Set the share relative path as the root path
m_path = FileName.DOS_SEPERATOR_STR;
}
else
{
if ( path.startsWith( FileName.DOS_SEPERATOR_STR) == false)
avmPath.append( AVM_SEPERATOR);
avmPath.append( path.replace( FileName.DOS_SEPERATOR, AVM_SEPERATOR));
}
m_avmPath = avmPath.toString();
// Indicate that the path is to a store relative path
m_levelId = LevelId.StorePath;
}
/**
* Generate a file id for the path
*
* @return int
*/
public final int generateFileId()
{
// Check if the path is a store path or pseudo path
int fid = -1;
if ( isLevel() == LevelId.StorePath)
{
// Use the share relative path to generate the file id
fid = getRelativePath().hashCode();
}
else if ( isPseudoPath())
{
// Create a relative path to the pseudo folder
StringBuilder relStr = new StringBuilder();
relStr.append( FileName.DOS_SEPERATOR);
switch( isLevel())
{
case StoreRoot:
relStr.append( getStoreName());
break;
case Head:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionNameHead);
break;
case HeadData:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionNameHead);
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.DataFolder);
break;
case HeadMetaData:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionNameHead);
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.MetaDataFolder);
break;
case VersionRoot:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionsFolder);
break;
case Version:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionsFolder);
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionFolderPrefix);
relStr.append( getVersion());
break;
case VersionData:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionsFolder);
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionFolderPrefix);
relStr.append( getVersion());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.DataFolder);
break;
case VersionMetaData:
relStr.append( getStoreName());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionsFolder);
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.VersionFolderPrefix);
relStr.append( getVersion());
relStr.append( FileName.DOS_SEPERATOR);
relStr.append( AVMPath.MetaDataFolder);
break;
}
// Generate the file id using the pseudo folder relative path
fid = relStr.toString().hashCode();
}
// Return the file id
return fid;
}
/**
* Return the AVM path details as a string
*
* @return String
*/
public String toString()
{
StringBuilder str = new StringBuilder();
switch ( m_levelId)
{
case Invalid:
str.append("[Invalid");
break;
case Root:
str.append("[Root");
break;
case StoreRoot:
str.append("[StoresRoot");
break;
case Head:
str.append("[");
str.append(getStoreName());
str.append(":HEAD");
break;
case HeadData:
str.append("[");
str.append(getStoreName());
str.append(":HEAD\\");
str.append( DataFolder);
break;
case HeadMetaData:
str.append("[");
str.append(getStoreName());
str.append(":HEAD\\");
str.append( MetaDataFolder);
break;
case VersionRoot:
str.append("[");
str.append(getStoreName());
str.append(":Versions");
break;
case Version:
str.append("[");
str.append(getStoreName());
str.append(":");
str.append(VersionFolderPrefix);
str.append(getVersion());
break;
case VersionData:
str.append("[");
str.append(getStoreName());
str.append(":");
str.append(VersionFolderPrefix);
str.append(getVersion());
str.append("\\");
str.append( DataFolder);
break;
case VersionMetaData:
str.append("[");
str.append(getStoreName());
str.append(":");
str.append(VersionFolderPrefix);
str.append(getVersion());
str.append("\\");
str.append( MetaDataFolder);
break;
case StorePath:
str.append("[");
str.append(getStoreName());
str.append(":");
str.append(VersionFolderPrefix);
str.append(getVersion());
str.append(",");
str.append(getRelativePath());
str.append(":");
str.append(getAVMPath());
break;
}
str.append("]");
return str.toString();
}
}