/**
* Copyright © 2006-2016 Web Cohesion (info@webcohesion.com)
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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 com.webcohesion.enunciate.module;
import com.webcohesion.enunciate.javac.decorations.DecoratedProcessingEnvironment;
import com.webcohesion.enunciate.javac.decorations.SourcePosition;
import javax.lang.model.element.Element;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* @author Ryan Heaton
*/
public abstract class BasicGeneratingModule extends BasicEnunicateModule {
/**
* Whether all files in the specified directory are newer than all the source files.
*
* @param destDir The directory.
* @return Whether the destination directory is up-to-date.
*/
public boolean isUpToDateWithSources(File destDir) {
Set<Element> apiElements = this.context.getApiElements();
DecoratedProcessingEnvironment env = this.context.getProcessingEnvironment();
long newestSourceTimestamp = 0;
File configFile = this.context.getConfiguration().getConfigFile();
if (configFile != null && configFile.exists()) {
newestSourceTimestamp = configFile.lastModified();
}
for (Element apiElement : apiElements) {
long sourceTimestamp = findSourceTimestamp(env, apiElement);
newestSourceTimestamp = Math.max(newestSourceTimestamp, sourceTimestamp);
}
return isUpToDate(newestSourceTimestamp, destDir);
}
public long findSourceTimestamp(DecoratedProcessingEnvironment env, Element apiElement) {
SourcePosition sp = env.findSourcePosition(apiElement);
URI uri = sp == null ? null : sp.getPath() == null ? null : sp.getPath().getCompilationUnit() == null ? null : sp.getPath().getCompilationUnit().getSourceFile() == null ? null : sp.getPath().getCompilationUnit().getSourceFile().toUri();
if (uri != null && "file".equalsIgnoreCase(uri.getScheme())) {
//it's a file uri.
return new File(uri.getPath()).lastModified();
}
return 0;
}
protected boolean isUpToDate(long newestSourceTimestamp, File destFile) {
List<File> destFiles;
if ((destFile == null) || (!destFile.exists())) {
debug("%s is NOT up-to-date because it doesn't exist.", destFile);
return false;
}
else if (!destFile.isDirectory()) {
destFiles = Arrays.asList(destFile);
}
else {
destFiles = new ArrayList<File>();
buildFileList(destFiles, destFile);
}
if (destFiles.isEmpty()) {
debug("%s is NOT up-to-date because it's an empty directory.", destFile);
return false;
}
else {
File oldestDest = getOldest(destFiles);
if (newestSourceTimestamp < oldestDest.lastModified()) {
debug("%s is up-to-date because its oldest file, %s, is younger than the youngest source file.", destFile, oldestDest);
return true;
}
else {
debug("%s is NOT up-to-date because its oldest file, %s, is older than the youngest source file.", destFile, oldestDest);
return false;
}
}
}
/**
* Get the latest modified file.
*
* @param files The files.
* @return The latest modified.
*/
protected File getYoungest(List<File> files) {
if ((files == null) || (files.isEmpty())) {
return null;
}
File latest = files.get(0);
for (File file : files) {
latest = latest.lastModified() > file.lastModified() ? latest : file;
}
return latest;
}
/**
* Get the earliest modified file.
*
* @param files The files.
* @return The earliest modified.
*/
protected File getOldest(List<File> files) {
if ((files == null) || (files.isEmpty())) {
return null;
}
File earliest = files.get(0);
for (File file : files) {
earliest = earliest.lastModified() < file.lastModified() ? earliest : file;
}
return earliest;
}
/**
* Adds all files in specified directories to a list.
*
* @param list The list.
* @param dirs The directories.
*/
protected void buildFileList(List<File> list, File... dirs) {
for (File dir : dirs) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
buildFileList(list, file);
}
else {
list.add(file);
}
}
}
}
}