001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with 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,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019
020package org.apache.isis.core.commons.config;
021
022import java.util.Collections;
023import java.util.List;
024
025import com.google.common.collect.Lists;
026
027import org.apache.isis.core.commons.components.Installer;
028
029public abstract class InstallerAbstract implements Installer, IsisConfigurationBuilderAware, IsisConfigurationAware {
030
031    private final String type;
032    private final String name;
033
034    private IsisConfigurationBuilder isisConfigurationBuilder;
035    private IsisConfiguration configuration;
036
037    /**
038     * Subclasses should pass in the type defined as a constant in the
039     * subinterface of Installer.
040     * 
041     * <p>
042     * For example, <tt>PersistenceMechanismInstaller</tt> has a constant
043     * <tt>PersistenceMechanismInstaller#TYPE</tt>. Any implementation of
044     * <tt>PersistenceMechanismInstaller</tt> should pass this constant value up
045     * to this constructor.
046     */
047    public InstallerAbstract(final String type, final String name) {
048        this.type = type;
049        this.name = name;
050    }
051
052    @Override
053    public String getType() {
054        return type;
055    }
056
057    @Override
058    public String getName() {
059        return name;
060    }
061
062    /**
063     * Returns <tt>[type.properties, type_name.properties</tt>.
064     * 
065     * <p>
066     * For example,
067     * <tt>[persistor.properties, persistor_in-memory.properties]</tt>.
068     * 
069     * @see #getType()
070     * @see #getName()
071     */
072    @Override
073    public List<String> getConfigurationResources() {
074        final List<String> resourceList = Lists.newArrayList();
075        final String componentImplementationFile = getType() + "_" + getName() + ".properties";
076        resourceList.add(componentImplementationFile);
077        final String componentFile = getType() + ".properties";
078        resourceList.add(componentFile);
079        addConfigurationResources(resourceList);
080        return Collections.unmodifiableList(resourceList);
081    }
082
083    /**
084     * Optional hook method to allow subclasses to specify any additional config
085     * resources.
086     */
087    protected void addConfigurationResources(final List<String> configurationResources) {
088    }
089
090    // ////////////////////////////////////////////////////
091    // init, shutdown
092    // ////////////////////////////////////////////////////
093
094    /**
095     * Default implementation does nothing.
096     */
097    @Override
098    public void init() {
099        // no-op implementation, subclasses may override!
100    }
101
102    /**
103     * Default implementation does nothing.
104     */
105    @Override
106    public void shutdown() {
107        // no-op implementation, subclasses may override!
108    }
109
110    /**
111     * Either this method or {@link #setConfiguration(IsisConfiguration)} should
112     * be called prior to calling {@link #getConfiguration()}.
113     * 
114     * <p>
115     * If a {@link #setConfiguration(IsisConfiguration) configuration} has
116     * already been provided, then throws {@link IllegalStateException}.
117     */
118    @Override
119    public void setConfigurationBuilder(final IsisConfigurationBuilder isisConfigurationBuilder) {
120        if (configuration != null) {
121            throw new IllegalStateException("A IsisConfiguration has already been provided.");
122        }
123        this.isisConfigurationBuilder = isisConfigurationBuilder;
124    }
125
126    /**
127     * Either this method or
128     * {@link #setConfigurationBuilder(IsisConfigurationBuilder)} should be
129     * called prior to calling {@link #getConfiguration()}.
130     * 
131     * <p>
132     * If a {@link #setConfigurationBuilder(IsisConfigurationBuilder)
133     * configuration builder} has already been provided, then throws
134     * {@link IllegalStateException}.
135     */
136    public void setConfiguration(final IsisConfiguration configuration) {
137        if (isisConfigurationBuilder != null) {
138            throw new IllegalStateException("A IsisConfigurationBuilder has already been provided.");
139        }
140        this.configuration = configuration;
141    }
142
143    /**
144     * Returns a <i>snapshot</i> of the current configuration provided by the
145     * {@link #setConfigurationBuilder(IsisConfigurationBuilder) injected}
146     * {@link IsisConfigurationBuilder}.
147     * 
148     * <p>
149     * Implementation note: the implementation is in fact just
150     * {@link InstallerLookupDefault}.
151     */
152    public IsisConfiguration getConfiguration() {
153        if (isisConfigurationBuilder != null) {
154            return isisConfigurationBuilder.getConfiguration();
155        } else if (configuration != null) {
156            return configuration;
157        } else {
158            throw new IllegalStateException("Neither a ConfigurationBuilder nor Configuration has not been provided");
159        }
160    }
161
162    /**
163     * Helper for subclasses implementing {@link #getTypes()}.
164     */
165    protected static List<Class<?>> listOf(final Class<?>... classes) {
166        return Collections.unmodifiableList(Lists.<Class<?>> newArrayList(classes));
167    }
168
169    /**
170     * Helper for subclasses implementing {@link #getTypes()}.
171     */
172    protected static List<Class<?>> listOf(final List<Class<?>> classList, final Class<?>... classes) {
173        final List<Class<?>> arrayList = Lists.<Class<?>> newArrayList(classes);
174        arrayList.addAll(0, classList);
175        return Collections.unmodifiableList(arrayList);
176    }
177
178}