/* * Copyright 2013 the original author or authors. * * Licensed 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.springframework.xd.dirt.plugins.job; import static org.springframework.xd.module.ModuleType.job; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.validation.constraints.AssertTrue; import org.springframework.xd.dirt.plugins.job.support.listener.XDJobListenerConstants; import org.springframework.xd.module.ModuleDefinition; import org.springframework.xd.module.options.ModuleOptionsMetadata; import org.springframework.xd.module.options.ModuleOptionsMetadataResolver; import org.springframework.xd.module.options.PojoModuleOptionsMetadata; import org.springframework.xd.module.options.spi.ModuleOption; import org.springframework.xd.module.options.spi.ProfileNamesProvider; import org.springframework.xd.rest.domain.util.TimeUtils; /** * A {@link ModuleOptionsMetadataResolver} that will dynamically add the module options (such as {@code makeUnique}) * supported by job modules. * * @see JobPlugin * @author Eric Bottard * @author Ilayaperumal Gopinathan */ public class JobPluginMetadataResolver implements ModuleOptionsMetadataResolver { @Override public ModuleOptionsMetadata resolve(ModuleDefinition moduleDefinition) { if (moduleDefinition.getType() == job) { return new PojoModuleOptionsMetadata(JobOptionsMetadata.class); } else { return null; } } public static class JobOptionsMetadata implements ProfileNamesProvider { private boolean makeUnique = true; private String numberFormat = ""; private String dateFormat = TimeUtils.DEFAULT_XD_DATE_FORMAT_PATTERN; private String listeners = ""; private String DISABLE_OPTION = "disable"; private final List<String> VALID_LISTENER_SUFFIXES = new ArrayList<String>( Arrays.asList(XDJobListenerConstants.XD_JOB_LISTENERS_SUFFIXES)); private Collection<String> listenerProfilesToAdd = new ArrayList<String>(); private static final Map<String, String> XD_JOB_LISTENER_PROFILES = new HashMap<String, String>(); static { // Profile names and bean names are equal for simplicity XD_JOB_LISTENER_PROFILES.put(XDJobListenerConstants.JOB_EXECUTION_EVENTS_SUFFIX, XDJobListenerConstants.XD_JOB_EXECUTION_LISTENER_BEAN); XD_JOB_LISTENER_PROFILES.put(XDJobListenerConstants.STEP_EXECUTION_EVENTS_SUFFIX, XDJobListenerConstants.XD_STEP_EXECUTION_LISTENER_BEAN); XD_JOB_LISTENER_PROFILES.put(XDJobListenerConstants.CHUNK_EVENTS_SUFFIX, XDJobListenerConstants.XD_CHUNK_LISTENER_BEAN); XD_JOB_LISTENER_PROFILES.put(XDJobListenerConstants.ITEM_EVENTS_SUFFIX, XDJobListenerConstants.XD_ITEM_LISTENER_BEAN); XD_JOB_LISTENER_PROFILES.put(XDJobListenerConstants.SKIP_EVENTS_SUFFIX, XDJobListenerConstants.XD_SKIP_LISTENER_BEAN); } public boolean isMakeUnique() { return makeUnique; } public String getNumberFormat() { return numberFormat; } public String getDateFormat() { return dateFormat; } public String getListeners() { return listeners; } @ModuleOption("whether always allow re-invocation of this job") public void setMakeUnique(boolean makeUnique) { this.makeUnique = makeUnique; } @ModuleOption("the number format to use when parsing numeric parameters") public void setNumberFormat(String numberFormat) { this.numberFormat = numberFormat; } @ModuleOption("the date format to use when parsing date parameters") public void setDateFormat(String dateFormat) { this.dateFormat = dateFormat; } @AssertTrue(message = "must be 'disable' or a combination of [job,step,chunk,item and skip]") public boolean isListenersListValid() { List<String> validOptions = new ArrayList<String>(VALID_LISTENER_SUFFIXES); validOptions.add(DISABLE_OPTION); StringTokenizer tokenizer = new StringTokenizer(listeners, ","); while (tokenizer.hasMoreElements()) { String optionName = (String) tokenizer.nextElement(); if (!validOptions.contains(optionName)) { return false; } } return true; } @ModuleOption("listeners from [job,step,chunk,item,skip] as csv or 'disable' (default enables all)") public void setListeners(String listeners) { this.listeners = listeners; } @Override public String[] profilesToActivate() { if (listeners.contains(DISABLE_OPTION)) { return NO_PROFILES; } else { StringTokenizer tokenizer = new StringTokenizer(listeners, ","); while (tokenizer.hasMoreElements()) { String suffixName = (String) tokenizer.nextElement(); listenerProfilesToAdd.add(XD_JOB_LISTENER_PROFILES.get(suffixName)); } if (listenerProfilesToAdd.isEmpty()) { listenerProfilesToAdd.addAll(XD_JOB_LISTENER_PROFILES.values()); } return listenerProfilesToAdd.toArray(new String[listenerProfilesToAdd.size()]); } } } }