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    /**
021     * Reference is a named (lazy) reference from one object to another. This data class is updated when the reference
022     * is resolved which can be immedately when the ref is created, or later when an instance with the referenced
023     * name is created.
024     * <p/>
025     * When the reference is resolved, an optional Action will be invoked which is commonly used to update a
026     * property on the source object of the reference.
027     */
028    public class Reference {
029        private final String name;
030        private boolean resolved;
031        private Object instance;
032        private Action action;
033    
034        /**
035         * Create a reference to the specified name.
036         * @param name the name of the referenced object
037         */
038        public Reference(String name) {
039            this.name = name;
040        }
041    
042        /**
043         * Gets the name of the referenced object.
044         * @return name the name of the referenced object
045         */
046        public String getName() {
047            return name;
048        }
049    
050        /**
051         * Has this reference been resolved?
052         * @return true if the reference has been resolved; false otherwise
053         */
054        public boolean isResolved() {
055            return resolved;
056        }
057    
058        /**
059         * Gets the referenced object instance or null if the reference has not been resolved yet;
060         *
061         * @return the referenced object instance or null
062         */
063        public Object get() {
064            return instance;
065        }
066    
067        /**
068         * Sets the referenced object instance.  If an action is registered the onSet method is invoked.
069         *
070         * @param object the reference instance
071         */
072        public void set(Object object) {
073            if (resolved) {
074                throw new ConstructionException("Reference has already been resolved");
075            }
076            resolved = true;
077            this.instance = object;
078            if (action != null) {
079                action.onSet(this);
080            }
081        }
082    
083        /**
084         * Registers an action to invoke when the instance is set.  If the instance, has already been set, the
085         * onSet method will immedately be invoked.
086         *
087         * @return the action to invoke when this refernce is resolved; not null
088         */
089        public void setAction(Action action) {
090            if (action == null) {
091                throw new NullPointerException("action is null");
092            }
093            this.action = action;
094            if (resolved) {
095                action.onSet(this);
096            }
097        }
098    
099        public static interface Action {
100            void onSet(Reference ref);
101        }
102    }