001    // Copyright 2004, 2005 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    
015    package org.apache.hivemind.impl;
016    
017    import java.util.List;
018    
019    import org.apache.hivemind.ApplicationRuntimeException;
020    import org.apache.hivemind.ErrorLog;
021    import org.apache.hivemind.Occurances;
022    import org.apache.hivemind.ServiceImplementationFactory;
023    import org.apache.hivemind.ServiceImplementationFactoryParameters;
024    import org.apache.hivemind.internal.Module;
025    import org.apache.hivemind.internal.ServiceImplementationConstructor;
026    import org.apache.hivemind.internal.ServicePoint;
027    import org.apache.hivemind.schema.Schema;
028    
029    /**
030     * Constructs a new service by invoking methods on another service (which implements the
031     * {@link org.apache.hivemind.ServiceImplementationFactory} interface.
032     * 
033     * @author Howard Lewis Ship
034     */
035    public final class InvokeFactoryServiceConstructor extends BaseLocatable implements
036            ServiceImplementationConstructor
037    {
038        private String _factoryServiceId;
039    
040        private ServicePoint _serviceExtensionPoint;
041    
042        private Module _contributingModule;
043    
044        /** List of {@link org.apache.hivemind.Element}, the raw XML parameters. */
045        private List _parameters;
046    
047        /** The factory service to be invoked. */
048        private ServiceImplementationFactory _factory;
049    
050        /** The parameters converted to objects as per the factory's parameter schema. */
051        private List _convertedParameters;
052    
053        // TODO: Should this method be synchronized?
054    
055        public Object constructCoreServiceImplementation()
056        {
057            if (_factory == null)
058            {
059                ServicePoint factoryPoint = _contributingModule.getServicePoint(_factoryServiceId);
060    
061                Occurances expected = factoryPoint.getParametersCount();
062    
063                _factory = (ServiceImplementationFactory) factoryPoint
064                        .getService(ServiceImplementationFactory.class);
065    
066                Schema schema = factoryPoint.getParametersSchema();
067    
068                ErrorLog errorLog = _serviceExtensionPoint.getErrorLog();
069    
070                SchemaProcessorImpl processor = new SchemaProcessorImpl(errorLog, schema);
071    
072                processor.process(_parameters, _contributingModule);
073    
074                _convertedParameters = processor.getElements();
075    
076                checkParameterCounts(errorLog, expected);
077            }
078    
079            try
080            {
081                ServiceImplementationFactoryParameters factoryParameters = new ServiceImplementationFactoryParametersImpl(
082                        _serviceExtensionPoint, _contributingModule, _convertedParameters);
083    
084                return _factory.createCoreServiceImplementation(factoryParameters);
085            }
086            catch (Exception ex)
087            {
088                throw new ApplicationRuntimeException(ex.getMessage(), getLocation(), ex);
089            }
090        }
091    
092        /**
093         * Checks that the number of parameter elements matches the expected count.
094         */
095        private void checkParameterCounts(ErrorLog log, Occurances expected)
096        {
097            int actual = _convertedParameters.size();
098    
099            if (expected.inRange(actual))
100                return;
101    
102            String message = ImplMessages.wrongNumberOfParameters(_factoryServiceId, actual, expected);
103    
104            log.error(message, getLocation(), null);
105        }
106    
107        public Module getContributingModule()
108        {
109            return _contributingModule;
110        }
111    
112        public void setContributingModule(Module module)
113        {
114            _contributingModule = module;
115        }
116    
117        public List getParameters()
118        {
119            return _parameters;
120        }
121    
122        public ServicePoint getServiceExtensionPoint()
123        {
124            return _serviceExtensionPoint;
125        }
126    
127        public void setParameters(List list)
128        {
129            _parameters = list;
130        }
131    
132        public void setFactoryServiceId(String string)
133        {
134            _factoryServiceId = string;
135        }
136    
137        public void setServiceExtensionPoint(ServicePoint point)
138        {
139            _serviceExtensionPoint = point;
140        }
141    
142    }