// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation // // 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.apache.tapestry5.ioc.internal; import org.apache.tapestry5.ioc.ObjectLocator; import org.apache.tapestry5.ioc.OrderedConfiguration; import org.apache.tapestry5.ioc.def.ContributionDef; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.internal.util.Orderer; import java.util.Map; /** * Wraps a {@link java.util.List} as a {@link org.apache.tapestry5.ioc.OrderedConfiguration}, implementing validation of * values provided to an {@link org.apache.tapestry5.ioc.OrderedConfiguration}. * * @param <T> */ public class ValidatingOrderedConfigurationWrapper<T> extends AbstractConfigurationImpl<T> implements OrderedConfiguration<T> { private final TypeCoercerProxy typeCoercer; private final Orderer<T> orderer; private final Class<T> expectedType; private final Map<String, OrderedConfigurationOverride<T>> overrides; private final ContributionDef contribDef; // Used to supply a default ordering constraint when none is supplied. private String priorId; public ValidatingOrderedConfigurationWrapper(Class<T> expectedType, ObjectLocator locator, TypeCoercerProxy typeCoercer, Orderer<T> orderer, Map<String, OrderedConfigurationOverride<T>> overrides, ContributionDef contribDef) { super(expectedType, locator); this.typeCoercer = typeCoercer; this.orderer = orderer; this.overrides = overrides; this.contribDef = contribDef; this.expectedType = expectedType; } @Override public void add(String id, T object, String... constraints) { T coerced = object == null ? null : typeCoercer.coerce(object, expectedType); // https://issues.apache.org/jira/browse/TAP5-1565 // Order each added contribution after the previously added contribution // (in the same method) if no other constraint is supplied. if (constraints.length == 0 && priorId != null) { // Ugly: reassigning parameters is yuck. constraints = new String[]{"after:" + priorId}; } orderer.add(id, coerced, constraints); priorId = id; } @Override public void override(String id, T object, String... constraints) { assert InternalUtils.isNonBlank(id); T coerced = object == null ? null : typeCoercer.coerce(object, expectedType); OrderedConfigurationOverride<T> existing = overrides.get(id); if (existing != null) throw new IllegalArgumentException(String.format("Contribution '%s' has already been overridden (by %s).", id, existing.getContribDef())); overrides.put(id, new OrderedConfigurationOverride<T>(orderer, id, coerced, constraints, contribDef)); } @Override public void addInstance(String id, Class<? extends T> clazz, String... constraints) { add(id, instantiate(clazz), constraints); } @Override public void overrideInstance(String id, Class<? extends T> clazz, String... constraints) { override(id, instantiate(clazz), constraints); } }