001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.xbean.recipe; 019 020 import java.util.Collections; 021 import java.util.List; 022 import java.lang.reflect.Type; 023 024 public class ReferenceRecipe extends AbstractRecipe { 025 private String referenceName; 026 027 public ReferenceRecipe() { 028 } 029 030 public ReferenceRecipe(String referenceName) { 031 this.referenceName = referenceName; 032 } 033 034 public String getReferenceName() { 035 return referenceName; 036 } 037 038 public void setReferenceName(String name) { 039 this.referenceName = name; 040 } 041 042 public List<Recipe> getNestedRecipes() { 043 ExecutionContext context = ExecutionContext.getContext(); 044 if (!context.containsObject(referenceName)) { 045 throw new NoSuchObjectException(referenceName); 046 } 047 048 Object object = ExecutionContext.getContext().getObject(referenceName); 049 if (object instanceof Recipe) { 050 Recipe recipe = (Recipe) object; 051 return Collections.singletonList(recipe); 052 } 053 return Collections.emptyList(); 054 } 055 056 public List<Recipe> getConstructorRecipes() { 057 return getNestedRecipes(); 058 } 059 060 public boolean canCreate(Type type) { 061 if (referenceName == null) { 062 throw new ConstructionException("Reference name has not been set"); 063 } 064 065 ExecutionContext context = ExecutionContext.getContext(); 066 067 Object object = context.getObject(referenceName); 068 if (object instanceof Recipe) { 069 Recipe recipe = (Recipe) object; 070 return recipe.canCreate(type); 071 } else { 072 return RecipeHelper.isInstance(type, object); 073 } 074 } 075 076 protected Object internalCreate(Type expectedType, boolean lazyRefAllowed) throws ConstructionException { 077 if (referenceName == null) { 078 throw new ConstructionException("Reference name has not been set"); 079 } 080 081 ExecutionContext context = ExecutionContext.getContext(); 082 083 Object object; 084 if (!context.containsObject(referenceName)) { 085 if (!lazyRefAllowed) { 086 throw new ConstructionException("Currently no object registered with name " + referenceName + 087 " and a lazy reference not allowed"); 088 } 089 090 Reference reference = new Reference(referenceName); 091 context.addReference(reference); 092 object = reference; 093 } else { 094 object = context.getObject(referenceName); 095 if (object instanceof Recipe) { 096 if (lazyRefAllowed) { 097 Reference reference = new Reference(referenceName); 098 context.addReference(reference); 099 object = reference; 100 } else { 101 Recipe recipe = (Recipe) object; 102 object = recipe.create(expectedType, false); 103 } 104 105 } 106 } 107 108 // add to execution context if name is specified 109 if (getName() != null) { 110 if (object instanceof Reference) { 111 object = new WrapperReference(getName(), (Reference) object); 112 } else { 113 ExecutionContext.getContext().addObject(getName(), object); 114 } 115 } 116 117 return object; 118 } 119 120 private static class WrapperReference extends Reference { 121 private final Reference delegate; 122 123 private WrapperReference(String name, Reference delegate) { 124 super(name); 125 this.delegate = delegate; 126 } 127 128 public boolean isResolved() { 129 return delegate.isResolved(); 130 } 131 132 public Object get() { 133 return delegate.get(); 134 } 135 136 public void set(Object object) { 137 if (isResolved()) { 138 throw new ConstructionException("Reference has already been resolved"); 139 } 140 141 // add to execution context 142 ExecutionContext.getContext().addObject(getName(), object); 143 144 delegate.set(object); 145 } 146 147 public void setAction(Action action) { 148 delegate.setAction(action); 149 } 150 } 151 }