001// Copyright 2006-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.services; 016 017import org.apache.tapestry5.Binding; 018import org.apache.tapestry5.ComponentResources; 019import org.apache.tapestry5.commons.Location; 020import org.apache.tapestry5.commons.internal.services.StringInterner; 021import org.apache.tapestry5.commons.internal.util.TapestryException; 022import org.apache.tapestry5.commons.util.ExceptionUtils; 023import org.apache.tapestry5.ioc.internal.util.InternalUtils; 024import org.apache.tapestry5.services.BindingFactory; 025import org.apache.tapestry5.services.BindingSource; 026 027import java.util.Map; 028 029public class BindingSourceImpl implements BindingSource 030{ 031 private final Map<String, BindingFactory> factories; 032 033 private final StringInterner interner; 034 035 public BindingSourceImpl(Map<String, BindingFactory> factories, StringInterner interner) 036 { 037 this.factories = factories; 038 this.interner = interner; 039 } 040 041 public Binding newBinding(String description, ComponentResources container, String defaultPrefix, String expression) 042 { 043 return newBinding(description, container, container, defaultPrefix, expression, null); 044 } 045 046 public Binding newBinding(String description, ComponentResources container, ComponentResources component, 047 String defaultPrefix, String expression, Location location) 048 { 049 assert InternalUtils.isNonBlank(description); 050 assert container != null; 051 assert InternalUtils.isNonBlank(defaultPrefix); 052 assert component != null; 053 054 // TAP5-845: The expression may be the empty string. This is ok, if it's compatible with 055 // the default prefix (the empty string is not a valid property expression, but is valid 056 // as a literal string, perhaps as an informal parameter). 057 058 // Location might be null 059 060 String subexpression = expression; 061 int colonx = expression.indexOf(':'); 062 063 BindingFactory factory = null; 064 065 if (colonx > 0) 066 { 067 String prefix = expression.substring(0, colonx); 068 069 factory = factories.get(prefix); 070 if (factory != null) 071 subexpression = expression.substring(colonx + 1); 072 } 073 074 if (factory == null) 075 factory = factories.get(defaultPrefix); 076 077 // And if that's null, what then? We assume that the default prefix is a valid prefix, 078 // or we'll get an NPE below and report it like any other error. 079 080 try 081 { 082 return factory.newBinding(interner.intern(description), container, component, subexpression, location); 083 } catch (Exception ex) 084 { 085 throw new TapestryException(String.format("Could not convert '%s' into a component parameter binding: %s", expression, ExceptionUtils.toMessage(ex)), location, ex); 086 } 087 } 088}