/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.isis.core.runtime.fixtures; import java.util.Collections; import java.util.List; import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.isis.applib.fixtures.CompositeFixture; import org.apache.isis.applib.fixtures.FixtureType; import org.apache.isis.applib.fixtures.InstallableFixture; import org.apache.isis.applib.fixtures.LogonFixture; import org.apache.isis.applib.fixtures.switchuser.SwitchUserService; import org.apache.isis.core.commons.lang.ObjectExtensions; import org.apache.isis.core.metamodel.services.ServicesInjector; import org.apache.isis.core.runtime.system.DeploymentType; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; import org.apache.isis.core.runtime.system.session.IsisSessionFactory; import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; // REVIEW: could probably inline public class FixturesInstallerDelegate { private static final Logger LOG = LoggerFactory.getLogger(FixturesInstallerDelegate.class); //region > Constructor, fields private final IsisSessionFactory isisSessionFactory; private final SwitchUserService switchUserService; //endregion public FixturesInstallerDelegate(final IsisSessionFactory isisSessionFactory) { this.isisSessionFactory = isisSessionFactory; switchUserService = isisSessionFactory.getServicesInjector().lookupService(SwitchUserService.class); } //region > addFixture, getFixtures protected final List<Object> fixtures = Lists.newArrayList(); /** * Automatically flattens any {@link List}s, recursively (depth-first) if * necessary. */ public void addFixture(final Object fixture) { if (fixture instanceof List) { final List<Object> fixtureList = ObjectExtensions.asListT(fixture, Object.class); for (final Object eachFixture : fixtureList) { addFixture(eachFixture); } } else { fixtures.add(fixture); } } /** * Returns all fixtures that have been {@link #addFixture(Object) added}. */ protected List<Object> getFixtures() { return Collections.unmodifiableList(fixtures); } //endregion //region > installFixtures /** * Installs all {{@link #addFixture(Object) added fixtures} fixtures (ie as * returned by {@link #getFixtures()}). * * <p> * The set of fixtures (as per {@link #getFixtures()}) is <i>not</i> cleared * after installation; the intention being to allow the * {@link org.apache.isis.core.runtime.fixtures.FixturesInstallerAbstract} to be * reused across multiple tests (REVIEW: does that make sense?) */ public final void installFixtures() { installFixtures(getFixtures()); } private void installFixtures(final List<Object> fixtures) { for (final Object fixture : fixtures) { installFixtureInTransaction(fixture); } } private void installFixtureInTransaction(final Object fixture) { getServicesInjector().injectServicesInto(fixture); installFixtures(getFixtures(fixture)); // now, install the fixture itself try { LOG.info("installing fixture: " + fixture); getTransactionManager().startTransaction(); installFixture(fixture); saveLogonFixtureIfRequired(fixture); getTransactionManager().endTransaction(); LOG.info("fixture installed"); } catch (final RuntimeException e) { LOG.error("installing fixture " + fixture.getClass().getName() + " failed; aborting ", e); try { getTransactionManager().abortTransaction(); } catch (final Exception e2) { LOG.error("failure during abort", e2); } throw e; } } /** * Obtain any child fixtures for this fixture. * * @param fixture */ private List<Object> getFixtures(final Object fixture) { if (fixture instanceof CompositeFixture) { final CompositeFixture compositeFixture = (CompositeFixture) fixture; return compositeFixture.getFixtures(); } return Collections.emptyList(); } private void installFixture(final Object fixture) { isisSessionFactory.getServicesInjector().injectServicesInto(fixture); if (fixture instanceof InstallableFixture) { final InstallableFixture installableFixture = (InstallableFixture) fixture; if (shouldInstallFixture(installableFixture)) { installableFixture.install(); } } if (fixture instanceof LogonFixture) { this.logonFixture = (LogonFixture) fixture; } } private boolean shouldInstallFixture(final InstallableFixture installableFixture) { final FixtureType fixtureType = installableFixture.getType(); if (fixtureType == FixtureType.DOMAIN_OBJECTS) { return !isisSessionFactory.getCurrentSession().getPersistenceSession().isFixturesInstalled(); } // fixtureType is OTHER; always install. return true; } //endregion //region > logonFixture /** * The requested {@link LogonFixture}, if any. * * <p> * Each fixture is inspected as it is {@link #installFixture(Object)}; if it * implements {@link LogonFixture} then it is remembered so that it can be * used later to automatically logon. */ private LogonFixture logonFixture; /** * The {@link LogonFixture}, if any. * * <p> * Used to automatically logon if in {@link DeploymentType#SERVER_PROTOTYPE} mode. */ public LogonFixture getLogonFixture() { return logonFixture; } private void saveLogonFixtureIfRequired(final Object fixture) { if (fixture instanceof LogonFixture) { if (logonFixture != null) { LOG.warn("Already specified logon fixture, using latest provided"); } this.logonFixture = (LogonFixture) fixture; } } //endregion //region > dependencies (derived) private ServicesInjector getServicesInjector() { return isisSessionFactory.getServicesInjector(); } private PersistenceSession getPersistenceSession() { return isisSessionFactory.getCurrentSession().getPersistenceSession(); } private IsisTransactionManager getTransactionManager() { return getPersistenceSession().getTransactionManager(); } //endregion }