/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* All rights reserved. This program and the accompanying materials are made available under
* the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
// BEGIN GENERATED CODE
package gov.redhawk.ide.codegen.util;
import gov.redhawk.ide.RedhawkIdeActivator;
import gov.redhawk.ide.codegen.CodegenFactory;
import gov.redhawk.ide.codegen.CodegenUtil;
import gov.redhawk.ide.codegen.ICodeGeneratorDescriptor;
import gov.redhawk.ide.codegen.IOperatingSystem;
import gov.redhawk.ide.codegen.IProcessor;
import gov.redhawk.ide.codegen.IScaComponentCodegen;
import gov.redhawk.ide.codegen.ImplementationSettings;
import gov.redhawk.ide.codegen.RedhawkCodegenActivator;
import gov.redhawk.ide.codegen.WaveDevSettings;
import gov.redhawk.ide.natures.ScaProjectNature;
import gov.redhawk.sca.util.SubMonitor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mil.jpeojtrs.sca.prf.PrfPackage;
import mil.jpeojtrs.sca.scd.ScdPackage;
import mil.jpeojtrs.sca.spd.Code;
import mil.jpeojtrs.sca.spd.Implementation;
import mil.jpeojtrs.sca.spd.Os;
import mil.jpeojtrs.sca.spd.Processor;
import mil.jpeojtrs.sca.spd.SoftPkg;
import mil.jpeojtrs.sca.spd.SpdFactory;
import mil.jpeojtrs.sca.spd.SpdPackage;
import mil.jpeojtrs.sca.util.DceUuidUtil;
import mil.jpeojtrs.sca.util.ScaResourceFactoryUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
/**
* A utility class for creating REDHAWK projects.
*
* @since 9.0
*/
public abstract class ProjectCreator {
protected ProjectCreator() {
}
/**
* Creates a new REDHAWK project without any files. Should be invoked in the context of a
* {@link org.eclipse.ui.actions.WorkspaceModifyOperation WorkspaceModifyOperation}.
* <p />
* This code is based on an IBM Developer Works article by Benoit Marchal.
*
* @param projectName The project name
* @param projectLocation the location on disk to create the project
* @param additionalNatureIDs The nature ID(s) (if any) to add to the project besides the {@link ScaProjectNature}
* @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be
* reported and that the operation cannot be canceled.
* @return The newly created project
* @throws CoreException A problem occurs while creating the project
*/
protected static IProject createEmptyProject(final String projectName, final java.net.URI projectLocation, final String[] additionalNatureIDs,
final IProgressMonitor monitor) throws CoreException {
final SubMonitor progress = SubMonitor.convert(monitor, "Creating REDHAWK Project", 3);
Set<String> natureIds = new HashSet<String>();
natureIds.addAll(Arrays.asList(additionalNatureIDs));
natureIds.add(ScaProjectNature.ID);
// Create and open the new project
final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
final IProject project = workspaceRoot.getProject(projectName);
IProjectDescription description = ResourcesPlugin.getWorkspace().newProjectDescription(project.getName());
if (projectLocation != null) {
description.setLocationURI(projectLocation);
}
project.create(description, progress.newChild(1));
project.open(progress.newChild(1));
// Add natures post-creation; otherwise they won't get configured
description = project.getDescription();
description.setNatureIds(natureIds.toArray(new String[natureIds.size()]));
project.setDescription(description, progress.newChild(1));
return project;
}
/**
* This method finds a file relative to the location of the spd file
*
* @param spdFile path to the SPD file
* @param localfilename name of the file to find
* @param filters filter for file types matching the desired file
* @return Path for the file found, specified in a dialog or null if no file
* was found
* @since 10.0
*/
public static IPath findLocalFile(final IPath spdFile, final IPath localfilename, final String[] filters) {
IPath localFile = spdFile.removeLastSegments(1).append(localfilename);
if (localFile.toFile().exists()) {
return localFile;
}
// First just see if it's easy to locate
localFile = spdFile.removeLastSegments(1).append(localfilename.lastSegment());
if (localFile.toFile().exists()) {
return localFile;
}
// Disable UI code
// // Now ask the user to locate it for us
// final FileDialog dialog = new FileDialog(this.getShell(), SWT.OPEN);
// dialog.setFilterExtensions(filters);
// dialog.setFileName(localfilename.lastSegment());
// dialog.setText("Locate missing file " + localfilename.lastSegment());
// final String selection = dialog.open();
//
// if (selection != null) {
// return new Path(selection);
// }
return null;
}
/**
* Copies the existing REDHAWK file into an empty REDHAWK project. Should be invoked in the
* context of a {@link org.eclipse.ui.actions.WorkspaceModifyOperation WorkspaceModifyOperation}.
*
* @param project The project to generate files in
* @param existingFilePath The existing file's path
* @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be
* reported and that the operation cannot be canceled.
* @return The newly created REDHAWK file
* @throws CoreException An error occurs while generating files
*/
public static IFile importFile(final IProject project, IFile destination, final IPath existingFilePath, final IProgressMonitor monitor)
throws CoreException {
final SubMonitor progress = SubMonitor.convert(monitor, "Importing REDHAWK file", 2);
final File existingFile = existingFilePath.toFile();
FileInputStream input = null;
try {
input = new FileInputStream(existingFile);
destination.create(input, true, progress.newChild(1));
} catch (final FileNotFoundException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "REDHAWK file (" + existingFilePath.toString() + ") does not exist"));
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// PASS
}
}
}
monitor.worked(1);
return destination;
}
/**
*
* Copies existing SPD, PRF and SCD files into an empty REDHAWK resource project. Should be invoked in the
* context of a {@link org.eclipse.ui.actions.WorkspaceModifyOperation WorkspaceModifyOperation}.
*
* @param project The project that the files will be imported to
* @param existingSpdFile Path to the existing SPD file
* @param implList List of implementations
* @param importedSettingsMap Mapping of imported implementations to their settings
* @param monitor The progress monitor
* @param id
* @return spdFile Returns a copy of the locally imported SPD file
* @throws CoreException
*/
public static IFile importFiles(final IProject project, final IPath existingSpdFile, final List<ImplementationAndSettings> implList,
final HashMap<String, Boolean> importedSettingsMap, final IProgressMonitor monitor) throws CoreException {
return importFiles(project, existingSpdFile, implList, importedSettingsMap, monitor, null);
}
/**
*
* Copies existing SPD, PRF and SCD files into an empty REDHAWK resource project. Should be invoked in the
* context of a {@link org.eclipse.ui.actions.WorkspaceModifyOperation WorkspaceModifyOperation}.
*
* @param project The project that the files will be imported to
* @param existingSpdFile Path to the existing SPD file
* @param implList List of implementations
* @param importedSettingsMap Mapping of imported implementations to their settings
* @param monitor The progress monitor
* @param id ID for new SPD
* @return spdFile Returns a copy of the locally imported SPD file
* @throws CoreException
* @since 9.1
*/
public static IFile importFiles(final IProject project, final IPath existingSpdFile, final List<ImplementationAndSettings> implList,
final HashMap<String, Boolean> importedSettingsMap, final IProgressMonitor monitor, String id) throws CoreException {
final SubMonitor subMonitor = SubMonitor.convert(monitor, "Importing REDHAWK XML", 7); // SUPPRESS CHECKSTYLE
// MagicNumber
// Copy the SPD file into the project
final IFile spdFile = project.getFile(project.getName() + SpdPackage.FILE_EXTENSION);
try {
spdFile.create(new FileInputStream(existingSpdFile.toFile()), true, subMonitor.newChild(1));
} catch (final FileNotFoundException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "SPD File does not exist"));
}
// Get the URI of the model file.
final URI fileURI = URI.createPlatformResourceURI(spdFile.getFullPath().toString(), true).appendFragment(SoftPkg.EOBJECT_PATH);
final ResourceSet set = ScaResourceFactoryUtil.createResourceSet();
final SoftPkg spd = (SoftPkg) set.getEObject(fileURI, true);
if (spd == null) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Invalid SPD File"));
}
spd.setName(project.getName());
if (id == null) {
spd.setId(DceUuidUtil.createDceUUID());
} else {
spd.setId(id);
}
if (spd.getPropertyFile() != null) {
final IPath propertyFilePath = new Path(spd.getPropertyFile().getLocalFile().getName());
final IPath propertyFile = ProjectCreator.findLocalFile(existingSpdFile, propertyFilePath, new String[] { "*" + PrfPackage.FILE_EXTENSION });
if (propertyFile == null) {
spd.setPropertyFile(null);
subMonitor.worked(1);
} else {
spd.getPropertyFile().getLocalFile().setName(project.getName() + PrfPackage.FILE_EXTENSION);
final IFile prfFile = project.getFile(spd.getPropertyFile().getLocalFile().getName());
try {
prfFile.create(new FileInputStream(propertyFile.toFile()), true, subMonitor.newChild(1));
} catch (final FileNotFoundException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Referenced PRF File " + propertyFilePath
+ " does not exist"));
}
}
} else {
subMonitor.notWorked(1);
}
if (spd.getDescriptor() != null) {
final IPath descriptorFilePath = new Path(spd.getDescriptor().getLocalfile().getName());
final IPath descriptorFile = ProjectCreator.findLocalFile(existingSpdFile, descriptorFilePath, new String[] { "*" + ScdPackage.FILE_EXTENSION });
if (descriptorFile == null) {
spd.setDescriptor(null);
subMonitor.worked(1);
} else {
spd.getDescriptor().getLocalfile().setName(project.getName() + ScdPackage.FILE_EXTENSION);
final IFile scdFile = project.getFile(spd.getDescriptor().getLocalfile().getName());
try {
scdFile.create(new FileInputStream(descriptorFile.toFile()), true, subMonitor.newChild(1));
} catch (final FileNotFoundException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Referenced SCD File " + descriptorFilePath
+ " does not exist"));
}
}
} else {
subMonitor.notWorked(1);
}
final IFile waveDevFile = project.getFile(CodegenUtil.getWaveDevSettingsURI(fileURI).lastSegment());
if (waveDevFile.exists()) {
waveDevFile.delete(true, subMonitor.newChild(1));
} else {
subMonitor.notWorked(1);
}
final Resource waveResource = set.createResource(URI.createPlatformResourceURI(waveDevFile.getFullPath().toString(), true));
final WaveDevSettings wavedevSettings = CodegenFactory.eINSTANCE.createWaveDevSettings();
waveResource.getContents().add(wavedevSettings);
// Remove the old implementations
spd.getImplementation().clear();
// Add the new implementations
for (final ImplementationAndSettings pair : implList) {
final Implementation impl = pair.getImplementation();
spd.getImplementation().add(impl);
wavedevSettings.getImplSettings().put(impl.getId(), pair.getImplementationSettings());
}
// Save settings
try {
final SubMonitor loopProgress = subMonitor.newChild(1).setWorkRemaining(set.getResources().size());
for (final Resource resource : set.getResources()) {
// Don't save if the URI isn't a platform one; this is probably just a reference to
// something in the SDRROOT
if (!resource.getURI().isPlatform()) {
loopProgress.notWorked(1);
continue;
}
loopProgress.setTaskName("Saving " + resource.getURI().lastSegment());
resource.save(null);
loopProgress.worked(1);
}
} catch (final IOException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Internal Error", e));
}
// Check to see if we have any imported settings to copy over
final SubMonitor loopProgress = subMonitor.newChild(1).setWorkRemaining(importedSettingsMap.size());
for (final String settingsId : importedSettingsMap.keySet()) {
// See if our settings wants to be copied over
if (importedSettingsMap.get(settingsId)) {
// Find its matching implementation
Implementation tempImpl = null;
for (final Implementation impl : spd.getImplementation()) {
if (impl.getId().equals(settingsId)) {
tempImpl = impl;
break;
}
}
final SubMonitor loopProgress2 = loopProgress.newChild(1).setWorkRemaining(3);
// Add the appropriate nature to the project via the generate
// command
CodegenFileHelper.addProjectNature(project, wavedevSettings.getImplSettings().get(settingsId), tempImpl, loopProgress2.newChild(1));
// Copy the source files
CodegenFileHelper.copySourceFiles(existingSpdFile, project, settingsId, loopProgress2.newChild(1));
// Refresh the output folder
project.getFolder(wavedevSettings.getImplSettings().get(settingsId).getOutputDir()).refreshLocal(IResource.DEPTH_INFINITE,
loopProgress2.newChild(1));
} else {
loopProgress.notWorked(1);
}
}
// Refresh the project and all subfolders
project.refreshLocal(IResource.DEPTH_INFINITE, subMonitor.newChild(1));
return spdFile;
}
/**
* IDE-1111: Make usable file/class names out of project names
* @param project The project for which to generate file names
* @return The base name to be used for files and classes in the project
* @since 11.0
*/
protected static String getBaseFileName(IProject project) {
return getBaseFileName(project.getName());
}
/**
* IDE-1111: Make usable file/class names out of project names
* @param name The original project name
* @return The base name to be used for files and classes in the project
* @since 11.0
*/
public static String getBaseFileName(String name) {
if (name == null) {
return null;
}
String[] tokens = name.split("\\.");
return tokens[tokens.length - 1];
}
/**
* Makes sure that a project has been cleaned out.
* @param project
* @throws CoreException
*/
public static void resetProject(final IProject project, final IProgressMonitor monitor) throws CoreException {
final SubMonitor progress = SubMonitor.convert(monitor, 1);
// IDE-1111 Make sure we are looking for correct file names
final IFile spdFile = project.getFile(getBaseFileName(project) + SpdPackage.FILE_EXTENSION);
final URI spdUri = URI.createPlatformResourceURI(spdFile.getFullPath().toString(), true).appendFragment(SoftPkg.EOBJECT_PATH);
final IFile waveDevFile = project.getFile(CodegenUtil.getWaveDevSettingsURI(spdUri).lastSegment());
if (waveDevFile.exists()) {
waveDevFile.delete(true, progress.newChild(1));
} else {
progress.setWorkRemaining(1);
}
final ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
final Resource waveResource = resourceSet.createResource(URI.createPlatformResourceURI(waveDevFile.getFullPath().toString(), true));
final WaveDevSettings wavedevSettings = CodegenFactory.eINSTANCE.createWaveDevSettings();
waveResource.getContents().add(wavedevSettings);
// Save EMF resources
try {
final SubMonitor loopProgress = progress.newChild(1).setWorkRemaining(resourceSet.getResources().size() * 2);
for (final Resource resource : resourceSet.getResources()) {
loopProgress.setTaskName("Saving " + resource.getURI().lastSegment());
// Save the resource to disk
resource.save(null);
loopProgress.worked(1);
// Generate an Eclipse resource change notification
String platformURI = resource.getURI().toPlatformString(true);
ResourcesPlugin.getWorkspace().getRoot().findMember(platformURI).refreshLocal(IResource.DEPTH_ZERO, progress.newChild(1));
}
} catch (final IOException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Internal Error", e));
}
}
/**
* Establishes initial implementation parameters based on the selected code generator.
*
* @param impl The implementation to be added
* @param settings The implementation's settings
* @throws CoreException An error occurs while working with the SPD or WaveDev files
*/
public static void setupImplementation(final SoftPkg softPkg, final Implementation impl, final ImplementationSettings settings) {
final ICodeGeneratorDescriptor codeGenDesc = RedhawkCodegenActivator.getCodeGeneratorsRegistry().findCodegen(settings.getGeneratorId());
if (codeGenDesc != null) {
IScaComponentCodegen generator;
try {
generator = codeGenDesc.getGenerator();
final Code codeSettings = generator.getInitialCodeSettings(softPkg, settings, impl);
impl.setCode(codeSettings);
} catch (CoreException e) {
RedhawkCodegenActivator.getDefault().getLog().log(
new Status(Status.WARNING, RedhawkCodegenActivator.PLUGIN_ID, "Errors wihle initializing code settings.", e));
}
if (impl.getOs().size() == 0) {
for (final IOperatingSystem tempOs : codeGenDesc.getOperatingSystems()) {
if (tempOs.isDefault()) {
final Os os = SpdFactory.eINSTANCE.createOs();
os.setName(tempOs.getName());
if (tempOs.getVersion() != "") {
os.setVersion(tempOs.getVersion());
}
impl.getOs().add(os);
}
}
}
if (impl.getProcessor().size() == 0) {
for (final IProcessor tempProc : codeGenDesc.getProcessors()) {
if (tempProc.isDefault()) {
final Processor proc = SpdFactory.eINSTANCE.createProcessor();
proc.setName(tempProc.getProcessorType());
impl.getProcessor().add(proc);
}
}
}
}
}
/**
* Directly adds an implementation to a {@link SoftPkg}.
*
* The {@link Implementation} will have its {@link Code} entry filled in
* based on the code generator template specified in {@link ImplementationSettings}.
* <p />
* This should be invoked in the context of a {@link org.eclipse.ui.actions.WorkspaceModifyOperation
* WorkspaceModifyOperation}.
* @param project
* @param impl
* @param settings
* @param monitor
* @deprecated This method will be removed in the future. Use the updated method which takes in the String spdName.
*/
@Deprecated
public static void addImplementation(final IProject project, final Implementation impl, final ImplementationSettings settings,
final IProgressMonitor monitor) throws CoreException {
addImplementation(project, null, impl, settings, monitor);
}
/**
* Directly adds an implementation to a {@link SoftPkg}.
*
* The {@link Implementation} will have its {@link Code} entry filled in
* based on the code generator template specified in {@link ImplementationSettings}.
* <p />
* This should be invoked in the context of a {@link org.eclipse.ui.actions.WorkspaceModifyOperation
* WorkspaceModifyOperation}.
*
* @param project
* @param impl
* @param command null if the implementation isn't being added within an editor context
* @since 10.0
*/
public static void addImplementation(final IProject project, final String spdName, final Implementation impl, final ImplementationSettings settings,
final IProgressMonitor monitor) throws CoreException {
// IDE-1111: Make sure correct file names are being used
String spdFileBaseName = (spdName == null) ? getBaseFileName(project) : getBaseFileName(spdName);
String spdFileName = spdFileBaseName + SpdPackage.FILE_EXTENSION; // SUPPRESS
final SubMonitor progress = SubMonitor.convert(monitor, 2);
final IFile spdFile = project.getFile(spdFileName);
final URI spdUri = URI.createPlatformResourceURI(spdFile.getFullPath().toString(), true).appendFragment(SoftPkg.EOBJECT_PATH);
final IFile waveDevFile = project.getFile(CodegenUtil.getWaveDevSettingsURI(spdUri).lastSegment());
final URI waveDevUri = URI.createPlatformResourceURI(waveDevFile.getFullPath().toString(), true);
final ResourceSet resourceSet = ScaResourceFactoryUtil.createResourceSet();
Assert.isTrue(waveDevFile.exists());
Assert.isTrue(spdFile.exists());
// Fill in the implementation's code settings (i.e. localfile, entrypoint, etc) using the code generator
// specified in the implementation settings
final SoftPkg eSpd = (SoftPkg) resourceSet.getEObject(spdUri, true);
final WaveDevSettings wavedevSettings = (WaveDevSettings) resourceSet.getResource(waveDevUri, true).getEObject("/");
Assert.isNotNull(eSpd);
Assert.isNotNull(wavedevSettings);
// Add the implementation to the SPD
if (!eSpd.getImplementation().contains(impl)) {
eSpd.getImplementation().add(impl);
}
Assert.isTrue(impl.eContainer().equals(eSpd));
// Create WaveDevSettings and add them to the WaveDev file
wavedevSettings.getImplSettings().put(impl.getId(), settings);
ProjectCreator.setupImplementation(eSpd, impl, settings);
final ICodeGeneratorDescriptor codeGenDesc = RedhawkCodegenActivator.getCodeGeneratorsRegistry().findCodegen(settings.getGeneratorId());
final IScaComponentCodegen generator = codeGenDesc.getGenerator();
final Code codeSettings = generator.getInitialCodeSettings(eSpd, settings, impl);
impl.setCode(codeSettings);
if (CodegenUtil.canPrimary(impl.getProgrammingLanguage().getName())) {
final EMap<String, ImplementationSettings> settingsMap = wavedevSettings.getImplSettings();
boolean primary = true;
for (final Implementation tmpImpl : eSpd.getImplementation()) {
if (tmpImpl.getProgrammingLanguage().getName().equals(impl.getProgrammingLanguage().getName())) {
final ImplementationSettings set = settingsMap.get(tmpImpl.getId());
if (set.isPrimary()) {
primary = false; // Don't change the primary if another implementation of the same language is
// primary
}
}
}
settings.setPrimary(primary);
}
// Save EMF resources
try {
final SubMonitor loopProgress = progress.newChild(1).setWorkRemaining(resourceSet.getResources().size() * 2);
for (final Resource resource : resourceSet.getResources()) {
loopProgress.setTaskName("Saving " + resource.getURI().lastSegment());
// Save the resource to disk
resource.save(null);
loopProgress.worked(1);
// Generate an Eclipse resource change notification
String platformURI = resource.getURI().toPlatformString(true);
ResourcesPlugin.getWorkspace().getRoot().findMember(platformURI).refreshLocal(IResource.DEPTH_ZERO, loopProgress.newChild(1));
}
} catch (final IOException e) {
throw new CoreException(new Status(IStatus.ERROR, RedhawkIdeActivator.PLUGIN_ID, "Internal Error", e));
}
}
/**
* Used to build out the .spec file directory block for namespaced resources. For example:<br/>
* %dir %{_prefix}/dom/waveforms/this<br/>
* %dir %{_prefix}/dom/waveforms/this/is<br/>
* %dir %{_prefix}/dom/waveforms/this/is/namespaced<br/>
* @since 11.1
*/
public static String createDirectoryBlock(String subDirectory) {
final String WAVEFORMS = "waveforms", NODES = "nodes";
StringBuilder builder = new StringBuilder();
// Preserve the existing prefix, as this is specific to the project type
String pathPrefix;
if (subDirectory.contains(WAVEFORMS)) {
pathPrefix = subDirectory.substring(0, subDirectory.indexOf(WAVEFORMS) + WAVEFORMS.length());
} else if (subDirectory.contains(NODES)) {
pathPrefix = subDirectory.substring(0, subDirectory.indexOf(NODES) + NODES.length());
} else {
return subDirectory;
}
// Making the assumption that the prefix includes the first three elements of the array
String[] textArray = subDirectory.split("/");
textArray = Arrays.copyOfRange(textArray, 3, textArray.length);
// Add lines to the directory block for each folder in the path
String pathSuffix = "";
for (int i = 0; i < textArray.length; i++) {
pathSuffix = pathSuffix + "/" + textArray[i];
if (i == textArray.length - 1) {
builder.append(pathPrefix + pathSuffix);
} else {
builder.append(pathPrefix + pathSuffix + "\n");
}
}
// Return the formated block
return builder.toString();
}
}