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.progmodel.facets.actions.command.configuration;
021
022import java.lang.reflect.Method;
023
024import org.apache.isis.applib.annotation.ActionSemantics.Of;
025import org.apache.isis.applib.annotation.Command;
026import org.apache.isis.applib.services.HasTransactionId;
027import org.apache.isis.core.commons.config.IsisConfiguration;
028import org.apache.isis.core.commons.config.IsisConfigurationAware;
029import org.apache.isis.core.metamodel.facetapi.FacetHolder;
030import org.apache.isis.core.metamodel.facetapi.FacetUtil;
031import org.apache.isis.core.metamodel.facetapi.FeatureType;
032import org.apache.isis.core.metamodel.facets.Annotations;
033import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
034import org.apache.isis.core.metamodel.facets.FacetedMethod;
035import org.apache.isis.core.metamodel.facets.actions.command.CommandFacet;
036import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
037import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetFactory;
038
039/**
040 * {@link CommandFacet} can also be installed via a naming convention, see
041 * {@link ActionInvocationFacetFactory}.
042 */
043public class CommandFromConfigurationFacetFactory extends FacetFactoryAbstract implements IsisConfigurationAware  {
044
045    private static final String  COMMAND_ACTIONS_KEY = "isis.services.command.actions";
046
047    private static enum ActionCategorization {
048        ALL,
049        IGNORE_SAFE,
050        NONE;
051        public static ActionCategorization parse(final String value) {
052            if ("ignoreQueryOnly".equalsIgnoreCase(value) || "ignoreSafe".equalsIgnoreCase(value)) {
053                return IGNORE_SAFE;
054            } else if ("all".equals(value)) {
055                return ALL;
056            } else {
057                return NONE;
058            }
059        }
060    }
061    
062    private IsisConfiguration configuration;
063
064    public CommandFromConfigurationFacetFactory() {
065        super(FeatureType.ACTIONS_ONLY);
066    }
067
068    @Override
069    public void process(final ProcessMethodContext processMethodContext) {
070
071        final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
072        final Class<?> cls = processMethodContext.getCls();
073        final Method method = processMethodContext.getMethod();
074
075        final ActionSemanticsFacet actionSemanticsFacet = facetHolder.getFacet(ActionSemanticsFacet.class);
076        if(actionSemanticsFacet == null) {
077            throw new IllegalStateException("Require ActionSemanticsFacet in order to process");
078        }
079        if(facetHolder.containsDoOpFacet(CommandFacet.class)) {
080            // do not replace
081            return;
082        }
083        if(HasTransactionId.class.isAssignableFrom(cls)) {
084            // do not install on any implementation of HasTransactionId
085            // (ie commands, audit entries, published events).
086            return; 
087        }
088        final ActionCategorization categorization = ActionCategorization.parse(configuration.getString(COMMAND_ACTIONS_KEY));
089        if(categorization == ActionCategorization.NONE) {
090            return;
091        }
092        if(actionSemanticsFacet.value() == Of.SAFE && categorization == ActionCategorization.IGNORE_SAFE) {
093            return;
094        }
095        final Command annotation = Annotations.getAnnotation(method, Command.class);
096        FacetUtil.addFacet(create(annotation, facetHolder));
097    }
098
099    private CommandFacet create(final Command annotation, final FacetHolder holder) {
100        return new CommandFacetFromConfiguration(Command.Persistence.PERSISTED, Command.ExecuteIn.FOREGROUND, holder);
101    }
102
103    // //////////////////////////////////////
104
105    @Override
106    public void setConfiguration(IsisConfiguration configuration) {
107        this.configuration = configuration;
108    }
109
110}