/*
* Copyright (C) 2014 Civilian Framework.
*
* Licensed under the Civilian License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.civilian-framework.org/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.civilian.internal.source;
import java.io.File;
import org.civilian.util.Arguments;
import org.civilian.util.Check;
import org.civilian.util.FileType;
/**
* Helper class to implement various ways to locate
* the output file of a Java class generated for a input file (e.g. a template).
* These types are supported:
* <ul>
* <li>write output to the same directory as the input file
* <li>write output to a specific file
* <li>write output to a specific directory
* <li>write output to the package directory of the class located under
* a specific source root directory
* </ul>
*/
public class OutputLocation
{
public static final OutputLocation OUTPUT_TO_INPUT_DIR = new OutputLocation(Type.TO_INPUT_DIR);
public static void printHelp(boolean allowSingleFile)
{
System.out.println("-out:input write to directory of the input file yes");
System.out.println("-out:dir <dir> write to directory");
if (allowSingleFile)
System.out.println("-out:file <file> write to file");
System.out.println("-out:package <dir> write to package subdirectory below dir");
}
/**
* Classifies OutputLocations.
*/
public enum Type
{
TO_INPUT_DIR (null, "input"),
TO_FILE (FileType.FILE, "file"),
TO_DIR (FileType.DIR, "dir"),
TO_PACKAGEDIR(FileType.DIR, "package");
Type(FileType fileType, String arg)
{
this.fileType = fileType;
this.arg = "-out:" + arg;
}
FileType fileType;
String arg;
}
public static OutputLocation parse(Arguments args, boolean required, boolean allowSingleFiles)
{
Type type = parseType(args);
if ((type == Type.TO_FILE) && !allowSingleFiles)
type = null;
if (type != null)
{
File paramFile = null;
if (type.fileType != null)
paramFile = args.nextFile("output argument", type.fileType);
return new OutputLocation(type, paramFile);
}
else if (required)
throw new IllegalArgumentException("unknown option " + args.next());
else
return null;
}
private static Type parseType(Arguments args)
{
for (Type type : Type.values())
{
if (args.consume(type.arg))
return type;
}
return null;
}
public OutputLocation(Type type)
{
this(type, null);
}
public OutputLocation(Type type, File paramFile)
{
type_ = Check.notNull(type, "type");
paramFile_ = paramFile;
if (paramFile != null)
{
if (type_.fileType == null)
throw new IllegalArgumentException("output " + type + " does not have a parameter file");
else
type_.fileType.check(paramFile);
}
else if (type_.fileType != null)
throw new IllegalArgumentException("output " + type + " needs parameter file");
}
public boolean needsPackage()
{
return type_ == Type.TO_PACKAGEDIR;
}
public OutputFile getOutputFile(String packageName, String fileName)
{
return getOutputFile(packageName, fileName, null);
}
public OutputFile getOutputFile(String packageName, String fileName, File inputFile)
{
if (type_ == Type.TO_PACKAGEDIR)
return getPackageDirOutput(packageName, fileName, inputFile);
File file;
switch(type_)
{
case TO_INPUT_DIR: if (inputFile == null)
throw new IllegalArgumentException("inputFile is null");
File dir = inputFile.isDirectory() ? inputFile : inputFile.getParentFile();
file = new File(dir, fileName);
break;
case TO_FILE: file = paramFile_;
break;
case TO_DIR: file = new File(paramFile_, fileName);
break;
default: throw new IllegalStateException("unknown: " + type_);
}
return new OutputFile(packageName, file);
}
private OutputFile getPackageDirOutput(String packageName, String fileName, File inputFile)
{
if (packageName == null)
{
if (inputFile == null)
throw new IllegalArgumentException("inputFile is null");
PackageDetector detector = new PackageDetector();
packageName = detector.detect(inputFile);
}
if (packageName != null)
{
String subDir = packageName.replace('.', '/');
File packageDir = new File(paramFile_, subDir);
File file = new File(packageDir, fileName);
return new OutputFile(packageName, file);
}
else
return null;
}
private Type type_;
private File paramFile_;
}