001package org.kuali.common.util.metainf.spring;
002
003import java.io.File;
004import java.util.ArrayList;
005import java.util.Comparator;
006import java.util.List;
007import java.util.Map;
008
009import com.google.common.base.Optional;
010import com.google.common.collect.Lists;
011import org.apache.commons.lang3.StringUtils;
012import org.kuali.common.util.metainf.model.*;
013import org.kuali.common.util.metainf.service.MetaInfUtils;
014import org.kuali.common.util.nullify.NullUtils;
015import org.kuali.common.util.project.ProjectUtils;
016import org.kuali.common.util.project.model.Build;
017import org.kuali.common.util.project.model.Project;
018import org.kuali.common.util.project.spring.AutowiredProjectConfig;
019import org.kuali.common.util.spring.SpringUtils;
020import org.kuali.common.util.spring.env.EnvironmentService;
021import org.kuali.common.util.spring.service.SpringServiceConfig;
022import org.springframework.beans.factory.annotation.Autowired;
023import org.springframework.context.annotation.Bean;
024import org.springframework.context.annotation.Configuration;
025import org.springframework.context.annotation.Import;
026
027import com.google.common.collect.Maps;
028
029/**
030 * TODO Should not be a class called {@code RiceXmlConfig} down here in kuali-util. Create a rice-util and move this there? Main issue preventing this from living in the rice-xml
031 * module itself is that it gets tricky having software used very early in the build lifecycle reside in the same project that makes use of it.
032 */
033@Configuration
034@Import({ AutowiredProjectConfig.class, MetaInfExecutableConfig.class, SpringServiceConfig.class })
035public class RiceXmlConfig implements MetaInfContextsConfig {
036
037        private static final boolean DEFAULT_GENERATE_RELATIVE_PATHS = true;
038        private static final String RELATIVE_KEY = MetaInfUtils.PROPERTY_PREFIX + ".xml.relative";
039        private static final String PREFIX = "xml";
040
041        // This is used in the rice-xml module to help locate the correct .resources file containing the XML to ingest
042        public static final String INGEST_FILENAME = "ingest";
043
044        @Autowired
045        EnvironmentService env;
046
047        @Autowired
048        Project project;
049
050        @Autowired
051        Build build;
052
053        @Override
054        @Bean
055        public List<MetaInfContext> metaInfContexts() {
056        List<MetaInfContext> metaInfContexts = new ArrayList<MetaInfContext>();
057        List<String> includeStrings = Lists.newArrayList("/initial-xml/", "/upgrades/*/");
058        for (String includeString : includeStrings) {
059            for (MetaInfDataType type : getTypes()) {
060                List<MetaInfContext> contexts = getMetaInfContexts(MetaInfGroup.OTHER, includeString, type);
061                metaInfContexts.addAll(contexts);
062            }
063        }
064                return metaInfContexts;
065        }
066
067        protected List<MetaInfContext> getMetaInfContexts(MetaInfGroup group, String includeString, MetaInfDataType type) {
068                List<MetaInfContext> metaInfContexts = Lists.newArrayList();
069                String includesKey = MetaInfConfigUtils.getIncludesKey(group, PREFIX);
070                String excludesKey = MetaInfConfigUtils.getExcludesKey(group, PREFIX);
071                File scanDir = build.getOutputDir();
072                String encoding = build.getEncoding();
073                Comparator<MetaInfResource> comparator = getComparator();
074        boolean relativePaths = env.getBoolean(RELATIVE_KEY, DEFAULT_GENERATE_RELATIVE_PATHS);
075        List<String> qualifiers = MetaInfUtils.getQualifiers(scanDir, project, Lists.<String>newArrayList(includeString), Lists.<String>newArrayList());
076        for (String qualifier : qualifiers) {
077            File outputFile = MetaInfUtils.getOutputFile(project, build, Optional.of(qualifier), Optional.<MetaInfDataLocation> absent(), Optional.of(type), INGEST_FILENAME);
078            Map<MetaInfGroup, String> defaultIncludes = getDefaultIncludes(project, qualifier, type);
079            Map<MetaInfGroup, String> defaultExcludes = getDefaultExcludes();
080            List<String> includes = SpringUtils.getNoneSensitiveListFromCSV(env, includesKey, defaultIncludes.get(group));
081            List<String> excludes = SpringUtils.getNoneSensitiveListFromCSV(env, excludesKey, defaultExcludes.get(group));
082            MetaInfContext context = new MetaInfContext.Builder(outputFile, encoding, scanDir).comparator(comparator).includes(includes).excludes(excludes).relativePaths(relativePaths).build();
083            metaInfContexts.add(context);
084        }
085        return metaInfContexts;
086        }
087
088    protected List<MetaInfDataType> getTypes() {
089        return Lists.newArrayList(MetaInfDataType.BOOTSTRAP, MetaInfDataType.DEMO, MetaInfDataType.TEST);
090    }
091
092        protected Comparator<MetaInfResource> getComparator() {
093                return new MetaInfResourcePathComparator();
094        }
095
096        protected Map<MetaInfGroup, String> getDefaultIncludes(Project project, String qualifier, MetaInfDataType type) {
097                String resourcePath = ProjectUtils.getResourcePath(project.getGroupId(), project.getArtifactId());
098                Map<MetaInfGroup, String> map = Maps.newHashMap();
099        List<String> paths = Lists.newArrayList(resourcePath, qualifier, type.name().toLowerCase(), "**/*.xml");
100                map.put(MetaInfGroup.OTHER, StringUtils.join(paths, "/"));
101                return map;
102        }
103
104        protected Map<MetaInfGroup, String> getDefaultExcludes() {
105                Map<MetaInfGroup, String> map = Maps.newHashMap();
106                map.put(MetaInfGroup.OTHER, NullUtils.NONE);
107                return map;
108        }
109
110}