inpuPath a former member of class FileBot. I decided to removed this member variable in the recent design for 
constructChildPath(). There are 5 test cases for this design specification - capturing files, 2 of the test case were failed, which is test case 4 and 5.
- one file is captured without sub folder.
- two files are captured without sub folder. 
- one files are captured when there is a sub folder.
- one files are captured in directory under test and one file in sub folder.
- zero file are captured in directory under test and one file in sub folder.
The root cause for this failure was due to the misused of 
inputPath as reference point in 
constructChildPath().
void FileBot::constructChildPath()
{
    vector<path> pathList;
 
    // where am I now?
    BOOST_LOG_TRIVIAL(info) << "current path: " << inputPath << inputPath.filename() << endl;
 
    // capture the paths/files list under the source
    copy(filesystem::directory_iterator(inputPath), filesystem::directory_iterator(), back_inserter(pathList));
    ...
    ...
}
For this purpose, I decide to remove this member variable to make 
constructChildPath() more robust in processing file directory.
 To do this, the first make over is to build a method to construct the path to feed 
directory_iterator().
string FileBot::constructPathAddress(FileNode *node)
{
    if( root == nullptr )
        return "";
    string filePath = "";
    if( node->getParentNode() != nullptr )
        filePath = constructPathAddress(node->getParentNode());
    return filePath + node->getName().string() + string(1, boost::filesystem::path::preferred_separator);
}
Unlike the previous version, the 
constructChildPath() has now been transformed into a recursive function. Take note on the 
inputPath is getting the outcome from 
constructPathAddress() and then feed into 
directory_iterator().
void FileBot::constructChildPath(FileNode *currentRootNode)
{
    vector<path> pathList;
    // construct path address
    string inputPath = constructPathAddress(currentRootNode);
    // capture the paths/files list under the source
    copy(filesystem::directory_iterator(inputPath), filesystem::directory_iterator(), back_inserter(pathList));
    std::sort(pathList.begin(), pathList.end());
    // scan through path and those files sit in that path
    // scan for files in sub directory if there is any sub directory in that path
    for(vector<path>::const_iterator it(pathList.begin()); it != pathList.end(); ++it) {
        string file = FileHelper::convertPathToString((*it));
        if( is_directory(file) ) {
            FileNode *node = new FileNode();
            node->setName(file.substr(file.find_last_of(boost::filesystem::path::preferred_separator) + 1, file.length()));
            node->setType('d');
            node->setParentNode(currentRootNode);
            currentRootNode->sibling.push_back(*node);
            BOOST_LOG_TRIVIAL(info) << "subFolderName : " << node->getName().string() << " : " << node;
            constructChildPath(node);
        }
        else {
            FileNode *node = new FileNode();
            node->setName(file.substr(file.find_last_of(boost::filesystem::path::preferred_separator) + 1, file.length()));
            node->setType('f');
            node->setParentNode(currentRootNode);
            currentRootNode->sibling.push_back(*node);
        }
    }
}
Last is to reassign the task of constructor to 
validatePath(). I just felt that this task doesn't suitable to put into the constructor since it only use by 
constructParentPath().
path FileBot::validatePath(boost::filesystem::path filePath)
{
    // remove trailing file separator if found any
    char lastChar = filePath.generic_string().at(filePath.generic_string().length() - 1);
    if( lastChar == '/' )
        filePath = filePath.generic_string().substr(0, filePath.generic_string().length() - 1);
    return filePath;
}
Then in 
constructParentPath() just call this method to update the input value again.
FileNode* FileBot::constructParentPath(boost::filesystem::path inputPath)
{
    inputPath = validatePath(inputPath);
    // bail out if the path doesn't exists
    if( !exists(inputPath.generic_string()) )
        return nullptr;
    ...
    ...
}
 
No comments:
Post a Comment