001/**
002 * Copyright 2005-2017 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.xml.config.spring;
017
018import com.google.common.base.Optional;
019import com.google.common.collect.ImmutableList;
020import com.google.common.collect.Lists;
021import com.google.common.collect.Maps;
022import org.apache.commons.lang3.StringUtils;
023import org.kuali.common.util.metainf.model.MetaInfContext;
024import org.kuali.common.util.metainf.model.MetaInfResource;
025import org.kuali.common.util.metainf.model.MetaInfResourcePathComparator;
026import org.kuali.common.util.metainf.service.MetaInfUtils;
027import org.kuali.common.util.metainf.spring.MetaInfConfigUtils;
028import org.kuali.common.util.metainf.spring.MetaInfContextsConfig;
029import org.kuali.common.util.metainf.spring.MetaInfDataLocation;
030import org.kuali.common.util.metainf.spring.MetaInfDataType;
031import org.kuali.common.util.metainf.spring.MetaInfExecutableConfig;
032import org.kuali.common.util.metainf.spring.MetaInfGroup;
033import org.kuali.common.util.nullify.NullUtils;
034import org.kuali.common.util.project.ProjectUtils;
035import org.kuali.common.util.project.model.Build;
036import org.kuali.common.util.project.model.Project;
037import org.kuali.common.util.project.spring.AutowiredProjectConfig;
038import org.kuali.common.util.spring.SpringUtils;
039import org.kuali.common.util.spring.env.EnvironmentService;
040import org.kuali.common.util.spring.service.SpringServiceConfig;
041import org.springframework.beans.factory.annotation.Autowired;
042import org.springframework.context.annotation.Bean;
043import org.springframework.context.annotation.Configuration;
044import org.springframework.context.annotation.Import;
045
046import java.io.File;
047import java.util.Comparator;
048import java.util.List;
049import java.util.Map;
050
051/**
052 * Defines the configuration for creating the xml property files that define how the database is created.
053 *
054 * @author Kuali Rice Team (rice.collab@kuali.org)
055 */
056@Configuration
057@Import({ AutowiredProjectConfig.class, MetaInfExecutableConfig.class, SpringServiceConfig.class })
058public class RiceXmlConfig implements MetaInfContextsConfig {
059
060    private static final Boolean DEFAULT_GENERATE_RELATIVE_PATHS = Boolean.TRUE;
061    private static final String RELATIVE_KEY = MetaInfUtils.PROPERTY_PREFIX + ".xml.relative";
062    private static final String PREFIX = "xml";
063    private static final String INGEST_FILENAME = "ingest";
064
065    // All paths must have the hardcoded separator to be consistent for deployment
066    private static final String PATH_SEPARATOR = "/";
067
068    private static final String INITIAL_XML_PATH = "initial-xml" + PATH_SEPARATOR + "2.3.0";
069    private static final String UPGRADE_XML_PATH = "upgrades" + PATH_SEPARATOR + "*";
070    private static final String ALL_XML_PATH = "**" + PATH_SEPARATOR + "*.xml";
071
072    /**
073     * The Spring environment.
074     */
075    @Autowired
076    EnvironmentService env;
077
078    /**
079     * The Rice Maven project.
080     */
081    @Autowired
082    Project project;
083
084    /**
085     * The build information.
086     */
087    @Autowired
088    Build build;
089
090    /**
091     * {@inheritDoc}
092     */
093    @Override
094    @Bean
095    public List<MetaInfContext> metaInfContexts() {
096        List<MetaInfContext> metaInfContexts = Lists.newArrayList();
097
098        List<MetaInfDataType> types = Lists.newArrayList(MetaInfDataType.BOOTSTRAP, MetaInfDataType.DEMO, MetaInfDataType.TEST);
099        List<String> qualifiers = Lists.newArrayList(INITIAL_XML_PATH, UPGRADE_XML_PATH);
100
101        for (MetaInfDataType type : types) {
102            for (String qualifier : qualifiers) {
103                List<MetaInfContext> contexts = getMetaInfContexts(MetaInfGroup.OTHER, qualifier, type);
104                metaInfContexts.addAll(contexts);
105            }
106        }
107
108        return ImmutableList.copyOf(metaInfContexts);
109    }
110
111    /**
112     * Creates a list of META-INF contexts for the given {@code group}, {@code qualifier}, and {@code type}.
113     *
114     * @param group the group of the data to create the contexts for
115     * @param qualifier the prefix to add to the initial resource path
116     * @param type the type of data to create the contexts for
117     *
118     * @return a list of META-INF contexts
119     */
120    protected List<MetaInfContext> getMetaInfContexts(MetaInfGroup group, String qualifier, MetaInfDataType type) {
121        List<MetaInfContext> metaInfContexts = Lists.newArrayList();
122
123        File scanDir = build.getOutputDir();
124        String encoding = build.getEncoding();
125
126        Comparator<MetaInfResource> comparator = new MetaInfResourcePathComparator();
127
128        String includesKey = MetaInfConfigUtils.getIncludesKey(group, PREFIX);
129        String excludesKey = MetaInfConfigUtils.getExcludesKey(group, PREFIX);
130
131        Boolean relativePaths = env.getBoolean(RELATIVE_KEY, DEFAULT_GENERATE_RELATIVE_PATHS);
132
133        List<String> pathQualifiers = MetaInfUtils.getQualifiers(scanDir, project, Lists.newArrayList(qualifier), Lists.<String> newArrayList());
134
135        for (String pathQualifier : pathQualifiers) {
136            File outputFile = MetaInfUtils.getOutputFile(project, build, Optional.of(pathQualifier),
137                    Optional.<MetaInfDataLocation> absent(), Optional.of(type), INGEST_FILENAME);
138
139            Map<MetaInfGroup, String> defaultIncludes = getDefaultIncludes(pathQualifier, type);
140            Map<MetaInfGroup, String> defaultExcludes = getDefaultExcludes();
141            List<String> includes = SpringUtils.getNoneSensitiveListFromCSV(env, includesKey, defaultIncludes.get(group));
142            List<String> excludes = SpringUtils.getNoneSensitiveListFromCSV(env, excludesKey, defaultExcludes.get(group));
143
144            MetaInfContext context = MetaInfContext.builder(outputFile, encoding, scanDir).comparator(comparator)
145                    .includes(includes).excludes(excludes).relativePaths(relativePaths.booleanValue()).build();
146            metaInfContexts.add(context);
147        }
148
149        return metaInfContexts;
150    }
151
152    /**
153     * Generates the default mapping of included paths from the given {@code qualifier} and {@code type}.
154     *
155     * @param qualifier the prefix to add to the initial resource path
156     * @param type the type of data to include
157     *
158     * @return the map of included paths
159     */
160    protected Map<MetaInfGroup, String> getDefaultIncludes(String qualifier, MetaInfDataType type) {
161        Map<MetaInfGroup, String> defaultIncludes = Maps.newEnumMap(MetaInfGroup.class);
162
163        String resourcePath = ProjectUtils.getResourcePath(project.getGroupId(), project.getArtifactId());
164        List<String> paths = Lists.newArrayList(resourcePath, qualifier, type.name().toLowerCase(), ALL_XML_PATH);
165
166        defaultIncludes.put(MetaInfGroup.OTHER, StringUtils.join(paths, PATH_SEPARATOR));
167
168        return defaultIncludes;
169    }
170
171    /**
172     * Generates the default mapping of excluded paths.
173     *
174     * @return the map of excluded paths
175     */
176    protected Map<MetaInfGroup, String> getDefaultExcludes() {
177        Map<MetaInfGroup, String> defaultExcludes = Maps.newEnumMap(MetaInfGroup.class);
178
179        defaultExcludes.put(MetaInfGroup.OTHER, NullUtils.NONE);
180
181        return defaultExcludes;
182    }
183
184}