/*
* Copyright 2014 Bernd Vogt and others.
*
* 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 org.sourcepit.b2.files;
import static org.sourcepit.b2.files.ModuleDirectory.FLAG_FORBIDDEN;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Named;
import org.sourcepit.common.utils.props.PropertiesSource;
@Named
public class ModuleDirectoryFactory {
private final Collection<FileFlagsProvider> infoProviders;
@Inject
public ModuleDirectoryFactory(List<FileFlagsProvider> infoProviders) {
this.infoProviders = infoProviders;
}
public ModuleDirectory create(File moduleDir, PropertiesSource properties) {
final Map<File, Integer> fileToFlagsMap = determineFileFlags(infoProviders, moduleDir, properties);
return new ModuleDirectory(moduleDir, fileToFlagsMap);
}
static Map<File, Integer> determineFileFlags(Collection<FileFlagsProvider> flagsProviders, File moduleDir,
PropertiesSource properties) {
final Map<File, Integer> fileToFlagsMap = new HashMap<File, Integer>();
collectAlreadyKnownFileFlags(flagsProviders, moduleDir, properties, fileToFlagsMap);
collectDeterminedFileFlags(flagsProviders, fileToFlagsMap, moduleDir, properties);
return fileToFlagsMap;
}
private static void collectAlreadyKnownFileFlags(Collection<FileFlagsProvider> flagsProviders, File moduleDir,
PropertiesSource properties, final Map<File, Integer> fileToFlagsMap) {
for (FileFlagsProvider flagsProvider : flagsProviders) {
final Map<File, Integer> providedFlags = flagsProvider.getAlreadyKnownFileFlags(moduleDir, properties);
applyFileFlags(fileToFlagsMap, providedFlags);
}
}
private static void applyFileFlags(final Map<File, Integer> fileToFlagsMap, final Map<File, Integer> providedFlags) {
if (providedFlags != null) {
for (Entry<File, Integer> entry : providedFlags.entrySet()) {
final File file = entry.getKey();
final int flags = getFlags(fileToFlagsMap, file) | getFlags(providedFlags, file);
if (flags != 0) {
fileToFlagsMap.put(file, Integer.valueOf(flags));
}
}
}
}
private static void collectDeterminedFileFlags(Collection<FileFlagsProvider> flagsProviders,
final Map<File, Integer> fileToFlagsMap, File moduleDir, PropertiesSource properties) {
final FileFlagsInvestigator investigator = getFileFlagsInvestigator(flagsProviders, moduleDir, properties);
if (investigator != null) {
collectDeterminedFileFlags(moduleDir, fileToFlagsMap, investigator);
}
}
private static FileFlagsInvestigator getFileFlagsInvestigator(Collection<FileFlagsProvider> flagsProviders,
File moduleDir, PropertiesSource properties) {
final List<FileFlagsInvestigator> investigators = new ArrayList<FileFlagsInvestigator>(flagsProviders.size());
for (FileFlagsProvider flagsProvider : flagsProviders) {
final FileFlagsInvestigator investigator = flagsProvider.createFileFlagsInvestigator(moduleDir, properties);
if (investigator != null) {
investigators.add(investigator);
}
}
return investigators.isEmpty() ? null : new FileFlagsInvestigator() {
@Override
public int determineFileFlags(File file) {
int flags = 0;
for (FileFlagsInvestigator investigator : investigators) {
flags |= investigator.determineFileFlags(file);
}
return flags;
}
@Override
public Map<File, Integer> getAdditionallyFoundFileFlags() {
final Map<File, Integer> fileToFlagsMap = new HashMap<File, Integer>();
for (FileFlagsInvestigator investigator : investigators) {
Map<File, Integer> fileFlags = investigator.getAdditionallyFoundFileFlags();
if (fileFlags != null) {
applyFileFlags(fileToFlagsMap, fileFlags);
}
}
return fileToFlagsMap;
}
};
}
private static void collectDeterminedFileFlags(File moduleDir, final Map<File, Integer> fileToFlagsMap,
final FileFlagsInvestigator investigator) {
new ModuleDirectory(moduleDir, fileToFlagsMap).accept(new FileVisitor<RuntimeException>() {
@Override
public boolean visit(File file, int flags) {
final int fileFlags = investigator.determineFileFlags(file);
if (fileFlags != 0) {
fileToFlagsMap.put(file, getFlags(fileToFlagsMap, file) | fileFlags);
if ((fileFlags & FLAG_FORBIDDEN) != 0) {
return false;
}
}
return true;
}
}, true, true);
final Map<File, Integer> additionallyFoundFileFlags = investigator.getAdditionallyFoundFileFlags();
if (additionallyFoundFileFlags != null) {
applyFileFlags(fileToFlagsMap, additionallyFoundFileFlags);
}
}
private static int getFlags(final Map<File, Integer> fileToFlagsMap, File file) {
final Integer oFlags = fileToFlagsMap.get(file);
return oFlags == null ? 0 : oFlags.intValue();
}
}