/** * 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.metamodel.services.grid; import java.util.List; import javax.annotation.Nullable; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.isis.applib.annotation.DomainService; import org.apache.isis.applib.annotation.NatureOfService; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.layout.component.Grid; import org.apache.isis.applib.services.grid.GridLoaderService; import org.apache.isis.applib.services.grid.GridService; import org.apache.isis.applib.services.grid.GridSystemService; @DomainService( nature = NatureOfService.DOMAIN, menuOrder = "" + Integer.MAX_VALUE ) public class GridServiceDefault implements GridService { private static final Logger LOG = LoggerFactory.getLogger(GridServiceDefault.class); public static final String COMMON_TNS = "http://isis.apache.org/applib/layout/component"; public static final String COMMON_SCHEMA_LOCATION = "http://isis.apache.org/applib/layout/component/component.xsd"; // ////////////////////////////////////// @Override public boolean supportsReloading() { return gridLoaderService.supportsReloading(); } @Override public void remove(final Class<?> domainClass) { gridLoaderService.remove(domainClass); } @Override @Programmatic public boolean existsFor(final Class<?> domainClass) { return gridLoaderService.existsFor(domainClass); } @Override @Programmatic public Grid load(final Class<?> domainClass) { return gridLoaderService.load(domainClass); } // ////////////////////////////////////// @Override @Programmatic public Grid defaultGridFor(Class<?> domainClass) { for (GridSystemService gridSystemService : gridNormalizerServices()) { Grid grid = gridSystemService.defaultGrid(domainClass); if(grid != null) { return grid; } } throw new IllegalStateException("No GridNormalizerService available to create grid for '" + domainClass.getName() + "'"); } @Override public Grid normalize(final Grid grid) { // if have .layout.json and then add a .layout.xml without restarting, then note that the .layout.xml won't // be picked up. To do so would require normalizing repeatedly in order to trample over the .layout.json's // original facets if(grid.isNormalized()) { return grid; } final Class<?> domainClass = grid.getDomainClass(); for (GridSystemService gridSystemService : gridNormalizerServices()) { gridSystemService.normalize(grid, domainClass); } final String tnsAndSchemaLocation = tnsAndSchemaLocation(grid); grid.setTnsAndSchemaLocation(tnsAndSchemaLocation); grid.setNormalized(true); return grid; } @Override @Programmatic public Grid complete(final Grid grid) { final Class<?> domainClass = grid.getDomainClass(); for (GridSystemService gridSystemService : gridNormalizerServices()) { gridSystemService.complete(grid, domainClass); } return grid; } @Override @Programmatic public Grid minimal(final Grid grid) { final Class<?> domainClass = grid.getDomainClass(); for (GridSystemService gridSystemService : gridNormalizerServices()) { gridSystemService.minimal(grid, domainClass); } return grid; } /** * Not public API, exposed only for testing. */ @Programmatic public String tnsAndSchemaLocation(final Grid grid) { final List<String> parts = Lists.newArrayList(); parts.add(COMMON_TNS); parts.add(COMMON_SCHEMA_LOCATION); for (GridSystemService gridSystemService : gridSystemServices) { final Class<? extends Grid> gridImpl = gridSystemService.gridImplementation(); if(gridImpl.isAssignableFrom(grid.getClass())) { parts.add(gridSystemService.tns()); parts.add(gridSystemService.schemaLocation()); } } return Joiner.on(" ").join(parts); } //////////////////////////////////////////////////////// private List<GridSystemService<?>> filteredGridSystemServices; /** * For all of the available {@link GridSystemService}s available, return only the first one for any that * are for the same grid implementation. * * <p> * This allows default implementations (eg for bootstrap3) to be overridden while also allowing for the more * general idea of multiple implementations. * </p> */ @Programmatic protected List<GridSystemService<?>> gridNormalizerServices() { if (filteredGridSystemServices == null) { List<GridSystemService<?>> services = Lists.newArrayList(); for (GridSystemService gridSystemService : this.gridSystemServices) { final Class gridImplementation = gridSystemService.gridImplementation(); final boolean notSeenBefore = FluentIterable.from(services).filter(new Predicate<GridSystemService<?>>() { @Override public boolean apply(@Nullable final GridSystemService<?> gridNormalizerService) { return gridNormalizerService.gridImplementation() == gridImplementation; } }).isEmpty(); if(notSeenBefore) { services.add(gridSystemService); } } filteredGridSystemServices = services; } return filteredGridSystemServices; } //////////////////////////////////////////////////////// @javax.inject.Inject GridLoaderService gridLoaderService; @javax.inject.Inject List<GridSystemService> gridSystemServices; }