package org.jboss.windup.graph.model.resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.EnumUtils;
import org.jboss.windup.graph.IndexType;
import org.jboss.windup.graph.Indexed;
import org.jboss.windup.graph.Indexes;
import org.jboss.windup.graph.frames.FrameBooleanDefaultValue;
import org.jboss.windup.graph.model.ArchiveModel;
import org.jboss.windup.graph.model.BelongsToProject;
import org.jboss.windup.graph.model.DuplicateProjectModel;
import org.jboss.windup.graph.model.ProjectModel;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.Adjacency;
import com.tinkerpop.frames.Property;
import com.tinkerpop.frames.modules.javahandler.JavaHandler;
import com.tinkerpop.frames.modules.javahandler.JavaHandlerContext;
import com.tinkerpop.frames.modules.typedgraph.TypeValue;
import org.jboss.windup.graph.model.WindupVertexFrame;
/**
* Represents a File on disk.
*/
@TypeValue(FileModel.TYPE)
public interface FileModel extends ResourceModel, BelongsToProject
{
String TYPE = "FileResource";
String PARENT_FILE = "parentFile";
String SHA1_HASH = "sha1Hash";
String MD5_HASH = "md5Hash";
String FILE_NAME = "fileName";
String FILE_PATH = "filePath";
String IS_DIRECTORY = "isDirectory";
String WINDUP_GENERATED = "windupGenerated";
String PARSE_ERROR = "parseError";
String ON_PARSE_ERROR = "onParseError";
enum OnParseError {
IGNORE, WARN;
OnParseError fromName(String name){
return EnumUtils.getEnum(OnParseError.class, StringUtils.upperCase(name));
}
}
/**
* Contains the File Name (the last component of the path). Eg, a file /tmp/foo/bar/file.txt would have fileName set to "file.txt"
*/
@Property(FILE_NAME)
String getFileName();
/**
* Contains the File Name (the last component of the path). Eg, a file /tmp/foo/bar/file.txt would have fileName set to "file.txt"
*/
@Indexes({
@Indexed,
@Indexed(value=IndexType.SEARCH, name="filenamesearchindex")
})
@Property(FILE_NAME)
void setFileName(String filename);
/**
* Contains the full path to the file (eg, /tmp/foo/bar/file.txt)
*/
@Indexed
@Property(FILE_PATH)
String getFilePath();
/**
* Contains the full path to the file (eg, /tmp/foo/bar/file.txt)
*/
// implemented via a handler that makes sure the isDirectory property is set as well
@JavaHandler
void setFilePath(String filePath);
/**
* Indicates whether the file is a directory or not
*/
@Property(IS_DIRECTORY)
boolean isDirectory();
/**
* Contains a MD5 Hash of the file
*/
@Property(MD5_HASH)
String getMD5Hash();
/**
* Contains a MD5 Hash of the file
*/
@Property(MD5_HASH)
void setMD5Hash(String md5Hash);
/**
* Contains a SHA1 Hash of the file
*/
@Property(SHA1_HASH)
@Indexed
String getSHA1Hash();
/**
* Contains a SHA1 Hash of the file
*/
@Property(SHA1_HASH)
void setSHA1Hash(String sha1Hash);
/**
* Did Windup encounter problems when parsing this file? If so, this will contain a description of the error.
*/
@Property(PARSE_ERROR)
String getParseError();
/**
* Did Windup encounter problems when parsing this file? If so, this will contain a description of the error.
*/
@Property(PARSE_ERROR)
void setParseError(String message);
/**
* What to do with a parsing error?
*/
@Property(ON_PARSE_ERROR)
OnParseError getOnParseError();
/**
* What to do with a parsing error?
*/
@Property(ON_PARSE_ERROR)
void setOnParseError(OnParseError ignore);
/**
* Parent directory
*/
@Adjacency(label = PARENT_FILE, direction = Direction.OUT)
FileModel getParentFile();
/**
* Parent directory
*/
@Adjacency(label = PARENT_FILE, direction = Direction.OUT)
void setParentFile(FileModel parentFile);
/**
* Files contained within this directory
*/
@Adjacency(label = PARENT_FILE, direction = Direction.IN)
Iterable<FileModel> getFilesInDirectory();
/**
* Add a file to this directory
*/
@Adjacency(label = PARENT_FILE, direction = Direction.IN)
void addFileToDirectory(FileModel fileModel);
/**
* Gets the {@link ProjectModel} that this file is a part of
*/
@Adjacency(label = ProjectModel.PROJECT_MODEL_TO_FILE, direction = Direction.IN)
ProjectModel getProjectModel();
/**
* Gets a {@link File} object representing this file
*/
@JavaHandler
File asFile() throws RuntimeException;
/**
* Returns an open {@link InputStream} for reading from this file
*/
@JavaHandler
InputStream asInputStream() throws RuntimeException;
/**
* Returns the path of this file within the archive (including all subarchives, etc)
*/
@JavaHandler
String getPrettyPath();
/**
* Returns the {@link ArchiveModel} that contains this file. If this file is an {@link ArchiveModel} then it will
* return itself.
*/
@JavaHandler
ArchiveModel getArchive();
/**
* Returns the path of this file within the parent project (format suitable for reporting)
*/
@JavaHandler
String getPrettyPathWithinProject();
/**
* Returns the application that this file is a part of. This is especially useful in the case of analyzing multiple application's, as we often
* need to know which application a particular file is associated with.
*
* This is a shortcut for calling getProjectModel().getRootProjectModel().
*/
@JavaHandler
ProjectModel getApplication();
/**
* Specifies if the given file was generated by windup or it originates from application.
*/
@Property(WINDUP_GENERATED)
Boolean isWindupGenerated();
/**
* Specifies if the given file was generated by windup or it originates from application.
*/
@FrameBooleanDefaultValue(false)
@Property(WINDUP_GENERATED)
void setWindupGenerated(boolean generated);
@Override
@JavaHandler
boolean belongsToProject(ProjectModel projectModel);
@Override
@JavaHandler
Iterable<ProjectModel> getRootProjectModels();
abstract class Impl implements FileModel, JavaHandlerContext<Vertex>, BelongsToProject
{
public ProjectModel getApplication()
{
ProjectModel projectModel = getProjectModel();
if (projectModel == null)
return null;
return projectModel.getRootProjectModel();
}
public String getPrettyPathWithinProject()
{
String result;
ProjectModel projectModel = getProjectModel();
if (projectModel == null)
{
// no project, just return the whole path
result = getPrettyPath();
}
else if (projectModel.getRootFileModel().getFilePath().equals(getFilePath()))
{
result = "";
}
else
{
String filename = getFileName();
if (getParentFile() == null)
{
result = filename;
}
else
{
String parentPrettyPath = getParentFile().getPrettyPathWithinProject();
result = StringUtils.isEmpty(parentPrettyPath) ? filename : parentPrettyPath + "/" + filename;
}
}
return result;
}
public String getPrettyPath()
{
String filename = getFileName();
String result;
if (getParentFile() == null)
{
result = filename;
}
else
{
result = getParentFile().getPrettyPath() + "/" + filename;
}
return result;
}
public void setFilePath(String filePath)
{
File file = new File(filePath);
// set the isDirectory attribute
it().setProperty(IS_DIRECTORY, file.isDirectory());
it().setProperty(FILE_PATH, file.getAbsolutePath());
it().setProperty(FILE_NAME, file.getName());
}
@Override
public ArchiveModel getArchive()
{
// required due to a quirk of the way frames works with @JavaHandler methods
WindupVertexFrame reframed = frame(it(), WindupVertexFrame.class);
if (reframed instanceof ArchiveModel)
{
return (ArchiveModel)reframed;
}
if (getParentFile() == null)
return null;
else
return getParentFile().getArchive();
}
@Override
public InputStream asInputStream() throws RuntimeException
{
try
{
if (this.getFilePath() == null)
return null;
File file = new File(getFilePath());
return new FileInputStream(file);
}
catch (Exception e)
{
throw new RuntimeException("Exception reading resource.", e);
}
}
@Override
public File asFile() throws RuntimeException
{
if (this.getFilePath() == null)
return null;
return new File(getFilePath());
}
@Override
public boolean belongsToProject(ProjectModel projectModel)
{
return this.getProjectModel().equals(this.getCanonicalProjectModel(projectModel));
}
@Override
public Iterable<ProjectModel> getRootProjectModels()
{
ProjectModel rootProjectModel = this.getProjectModel().getRootProjectModel();
List<ProjectModel> projectModelList = new ArrayList<>();
projectModelList.add(rootProjectModel);
return projectModelList;
}
}
}