001/*
002 * Copyright 2012-2017 the original author or authors.
003 *
004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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 */
016
017package org.springframework.boot.autoconfigure.condition;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.springframework.context.annotation.Condition;
023
024/**
025 * {@link Condition} that will match when all nested class conditions match. Can be used
026 * to create composite conditions, for example:
027 *
028 * <pre class="code">
029 * static class OnJndiAndProperty extends AllNestedConditions {
030 *
031 *    OnJndiAndProperty() {
032 *        super(ConfigurationPhase.PARSE_CONFIGURATION);
033 *    }
034 *
035 *    &#064;ConditionalOnJndi()
036 *    static class OnJndi {
037 *    }
038 *
039 *    &#064;ConditionalOnProperty("something")
040 *    static class OnProperty {
041 *    }
042 *
043 * }
044 * </pre>
045 * <p>
046 * The
047 * {@link org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase
048 * ConfigurationPhase} should be specified according to the conditions that are defined.
049 * In the example above, all conditions are static and can be evaluated early so
050 * {@code PARSE_CONFIGURATION} is a right fit.
051 *
052 * @author Phillip Webb
053 * @since 1.3.0
054 */
055public abstract class AllNestedConditions extends AbstractNestedCondition {
056
057        public AllNestedConditions(ConfigurationPhase configurationPhase) {
058                super(configurationPhase);
059        }
060
061        @Override
062        protected ConditionOutcome getFinalMatchOutcome(MemberMatchOutcomes memberOutcomes) {
063                boolean match = hasSameSize(memberOutcomes.getMatches(), memberOutcomes.getAll());
064                List<ConditionMessage> messages = new ArrayList<>();
065                messages.add(ConditionMessage.forCondition("AllNestedConditions")
066                                .because(memberOutcomes.getMatches().size() + " matched "
067                                                + memberOutcomes.getNonMatches().size() + " did not"));
068                for (ConditionOutcome outcome : memberOutcomes.getAll()) {
069                        messages.add(outcome.getConditionMessage());
070                }
071                return new ConditionOutcome(match, ConditionMessage.of(messages));
072        }
073
074        private boolean hasSameSize(List<?> list1, List<?> list2) {
075                return list1.size() == list2.size();
076        }
077
078}