Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AIProject.java #3303

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,147 +8,143 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import javax.swing.JOptionPane;

/**
* A representation of an App Inventor project. This includes its path, name,
* list of assets, list of screens and project properties file.
*
* list of assets, list of screens, and project properties file.
*
* <p>Provides functionality to validate and extract components of the project.
*
* @author [email protected] (Kate Feeney)
*/
public class AIProject {

// Backing for the project's directory path from home
private String projectPath;

// Backing for the list of AIScreens
private List<AIScreen> screensList;

// Backing for the list of AIAssets
private List<AIAsset> assetsList;

// Backing for the path to the projects properties file
private String propertiesFilePath;

// Backing for if the project is a valid source file
private boolean valid;

/**
* Creates a new AIProject.
*
* @param projectPath the path to the project from the home directory
*/
public AIProject(String projectPath) {
try {
this.projectPath = projectPath;
// Create screens list.
this.screensList = new LinkedList<AIScreen>();
// Create assets list.
this.assetsList = new LinkedList<AIAsset>();
// Go through each file in the project and create the appropriate classes.
Enumeration<? extends ZipEntry> e = new ZipFile(new File(projectPath)).entries();
while (e.hasMoreElements()) {
// fileName is the path of the file in the project file.
String fileName = (new ZipEntry(e.nextElement())).getName();
// Create an AIScreen from any screen file in the project's src folder.
if (fileName.startsWith("src") && fileName.endsWith(".scm")) {
AIScreen screen = new AIScreen(fileName);
screensList.add(screen);
// Create an AIAsset from any file in the project's assets folder.
} else if (fileName.startsWith("assets")) {
AIAsset asset = new AIAsset(fileName);
assetsList.add(asset);
} else if (fileName.endsWith("project.properties")) {
this.setPropertiesFilePath(fileName);
private final String projectPath; // Path to the project file
private final List<AIScreen> screensList; // List of screens in the project
private final List<AIAsset> assetsList; // List of assets in the project
private String propertiesFilePath; // Path to the project's properties file
private boolean valid; // Indicates whether the project is valid

/**
* Creates a new AIProject.
*
* @param projectPath the path to the project file (ZIP archive)
*/
public AIProject(String projectPath) {
this.projectPath = projectPath;
this.screensList = new LinkedList<>();
this.assetsList = new LinkedList<>();
this.valid = false;
initializeProject();
}

/**
* Initializes the project by reading the ZIP file and extracting components.
*/
private void initializeProject() {
try (ZipFile zipFile = new ZipFile(new File(projectPath))) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();

while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String fileName = entry.getName();

if (fileName.startsWith("src") && fileName.endsWith(".scm")) {
screensList.add(new AIScreen(fileName));
} else if (fileName.startsWith("assets")) {
assetsList.add(new AIAsset(fileName));
} else if (fileName.endsWith("project.properties")) {
propertiesFilePath = fileName;
}
}

validateProject();
} catch (ZipException e) {
showErrorDialog("The selected file is not a valid project source file. Source files must be ZIP archives.");
} catch (IOException e) {
showErrorDialog("An error occurred while reading the project file.");
}
}

/**
* Validates the project by ensuring essential components are present.
*/
private void validateProject() {
valid = !screensList.isEmpty() && propertiesFilePath != null;
if (!valid) {
showErrorDialog("The selected project is missing essential components (e.g., screens or properties file).");
}
}
// Check if valid project, if not show error.
valid = screensList != null && propertiesFilePath != null;
if (!valid) {
JOptionPane.showMessageDialog(AIMerger.getInstance().myCP, "The selected project is not a"
+ " project source file! Project source files are zip files.", "File error",
JOptionPane.ERROR_MESSAGE);
}
} catch (ZipException e) {
JOptionPane.showMessageDialog(AIMerger.getInstance().myCP,
"The selected project is not a project source file! Project source files are zip files.",
"File error", JOptionPane.ERROR_MESSAGE);
valid = false;
} catch (IOException e) {
JOptionPane.showMessageDialog(AIMerger.getInstance().myCP,
"The selected project is not a project source file! Project source files are zip files.",
"File error", JOptionPane.ERROR_MESSAGE);
valid = false;
}
}

/**
* Returns the AIProject's name.
*
* @return AIProject's name
*/
public String getProjectName() {
// The projectName is the name of the zip file.
if (projectPath.contains(File.separator)) {
return projectPath.substring(projectPath.lastIndexOf(File.separator) + 1,
projectPath.lastIndexOf("."));
} else {
return projectPath;

/**
* Displays an error dialog with the given message.
*
* @param message the error message to display
*/
private void showErrorDialog(String message) {
JOptionPane.showMessageDialog(
AIMerger.getInstance().myCP,
message,
"File Error",
JOptionPane.ERROR_MESSAGE
);
}

/**
* Returns the name of the project, derived from the ZIP file name.
*
* @return the project name
*/
public String getProjectName() {
File file = new File(projectPath);
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf('.');
return dotIndex > 0 ? fileName.substring(0, dotIndex) : fileName;
}

/**
* Returns the path to the project file.
*
* @return the project file path
*/
public String getProjectPath() {
return projectPath;
}

/**
* Returns the list of screens in the project.
*
* @return a list of {@link AIScreen} objects
*/
public List<AIScreen> getScreensList() {
return screensList;
}

/**
* Returns the list of assets in the project.
*
* @return a list of {@link AIAsset} objects
*/
public List<AIAsset> getAssetsList() {
return assetsList;
}

/**
* Returns the path to the project's properties file within the ZIP archive.
*
* @return the properties file path
*/
public String getPropertiesFilePath() {
return propertiesFilePath;
}

/**
* Checks whether the project is valid for merging.
*
* @return {@code true} if the project is valid, {@code false} otherwise
*/
public boolean isValid() {
return valid;
}
}

/**
* Returns the AIProject's path from home directory.
*
* @return AIProject's path from home directory
*/
public String getProjectPath() {
return projectPath;
}

/**
* Returns the AIProject's list of AIScreens.
*
* @return list of project's AIScreens
*/
public List<AIScreen> getScreensList() {
return screensList;
}

/**
* Returns the AIProject's list of AIAssets.
*
* @return list of project's AIAssets
*/
public List<AIAsset> getAssetsList() {
return assetsList;
}

/**
* Returns the path to the projects properties file from project file.
*
* @return path to project's properties file within the project file
*/
public String getPropertiesFilePath() {
return propertiesFilePath;
}

/**
* Sets the projects properties file
*
* @param propertiesFilePath the path to the project's properties file within the project
*/
public void setPropertiesFilePath(String propertiesFilePath) {
this.propertiesFilePath = propertiesFilePath;
}

/**
* Returns if the project is valid and can be used for a merge.
*
* @return if project is valid
*/
public boolean isValid() {
return this.valid;
}
}
}