001/* 002 * Copyright 2013-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.core.jsr.configuration.support; 017 018import java.util.Enumeration; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Properties; 022 023import org.springframework.util.Assert; 024 025/** 026 * <p> 027 * Context object to hold parsed JSR-352 batch properties, mapping properties to beans / 028 * "batch artifacts". Used internally when parsing property tags from a batch configuration 029 * file and to obtain corresponding values when injecting into batch artifacts. 030 * </p> 031 * 032 * @author Chris Schaefer 033 * @author Michael Minella 034 * @since 3.0 035 */ 036public class BatchPropertyContext { 037 private static final String PARTITION_INDICATOR = ":partition"; 038 039 private Properties jobProperties = new Properties(); 040 private Map<String, Properties> stepProperties = new HashMap<String, Properties>(); 041 private Map<String, Properties> artifactProperties = new HashMap<String, Properties>(); 042 private Map<String, Map<String, Properties>> stepArtifactProperties = new HashMap<String, Map<String, Properties>>(); 043 044 /** 045 * <p> 046 * Obtains the Job level properties. 047 * </p> 048 * 049 * @return the Job level properties 050 */ 051 public Properties getJobProperties() { 052 return jobProperties; 053 } 054 055 /** 056 * <p> 057 * Adds Job level properties to the context. 058 * </p> 059 * 060 * @param properties the job {@link Properties} to add 061 */ 062 public void setJobProperties(Properties properties) { 063 Assert.notNull(properties, "Job properties cannot be null"); 064 this.jobProperties.putAll(properties); 065 } 066 067 /** 068 * <p> 069 * Obtains the Step level properties for the provided Step name. 070 * </p> 071 * 072 * @param stepName the Step name to obtain properties for 073 * @return the {@link Properties} for the Step 074 */ 075 public Properties getStepProperties(String stepName) { 076 Assert.hasText(stepName, "Step name must be provided"); 077 Properties properties = new Properties(); 078 079 if(stepProperties.containsKey(stepName)) { 080 properties.putAll(stepProperties.get(stepName)); 081 } 082 083 if(stepName.contains(PARTITION_INDICATOR)) { 084 String parentStepName = stepName.substring(0, stepName.indexOf(PARTITION_INDICATOR)); 085 properties.putAll(getStepProperties(parentStepName)); 086 } 087 088 return properties; 089 } 090 091 /** 092 * <p> 093 * Adds Step level properties to the context. 094 * </p> 095 * 096 * @param properties the step {@link Properties} to add 097 */ 098 public void setStepProperties(Map<String, Properties> properties) { 099 Assert.notNull(properties, "Step properties cannot be null"); 100 101 for(Map.Entry<String, Properties> propertiesEntry : properties.entrySet()) { 102 String stepName = propertiesEntry.getKey(); 103 Properties stepProperties = propertiesEntry.getValue(); 104 105 if (!stepProperties.isEmpty()) { 106 if (this.stepProperties.containsKey(stepName)) { 107 Properties existingStepProperties = this.stepProperties.get(stepName); 108 109 Enumeration<?> stepPropertyNames = stepProperties.propertyNames(); 110 111 while(stepPropertyNames.hasMoreElements()) { 112 String propertyEntryName = (String) stepPropertyNames.nextElement(); 113 existingStepProperties.put(propertyEntryName, stepProperties.getProperty(propertyEntryName)); 114 } 115 116 this.stepProperties.put(stepName, existingStepProperties); 117 } else { 118 this.stepProperties.put(stepName, propertiesEntry.getValue()); 119 } 120 } 121 } 122 } 123 124 /** 125 * <p> 126 * Convenience method to set step level properties. Simply wraps the provided parameters 127 * and delegates to {@link #setStepProperties(java.util.Map)}. 128 * </p> 129 * 130 * @param stepName the step name to set {@link Properties} for 131 * @param properties the {@link Properties} to set 132 */ 133 public void setStepProperties(String stepName, Properties properties) { 134 Assert.hasText(stepName, "Step name must be provided"); 135 Assert.notNull(properties, "Step properties must not be null"); 136 137 Map<String, Properties> stepProperties = new HashMap<String, Properties>(); 138 stepProperties.put(stepName, properties); 139 140 setStepProperties(stepProperties); 141 } 142 143 /** 144 * <p> 145 * Obtains the batch {@link Properties} for the provided artifact name. 146 * </p> 147 * 148 * @param artifactName the batch artifact to obtain properties for 149 * @return the {@link Properties} for the provided batch artifact 150 */ 151 public Properties getArtifactProperties(String artifactName) { 152 Properties properties = new Properties(); 153 154 if (artifactProperties.containsKey(artifactName)) { 155 properties.putAll(artifactProperties.get(artifactName)); 156 } 157 158 return properties; 159 } 160 161 /** 162 * <p> 163 * Adds non-step artifact properties to the context. 164 * </p> 165 * 166 * @param properties the artifact {@link Properties} to add 167 */ 168 public void setArtifactProperties(Map<String, Properties> properties) { 169 Assert.notNull(properties, "Step properties cannot be null"); 170 171 for(Map.Entry<String, Properties> propertiesEntry : properties.entrySet()) { 172 String artifactName = propertiesEntry.getKey(); 173 Properties artifactProperties = propertiesEntry.getValue(); 174 175 if(!artifactProperties.isEmpty()) { 176 this.artifactProperties.put(artifactName, artifactProperties); 177 } 178 } 179 } 180 181 /** 182 * <p> 183 * Obtains the batch {@link Properties} for the provided Step and artifact name. 184 * </p> 185 * 186 * @param stepName the Step name the artifact is associated with 187 * @param artifactName the artifact name to obtain {@link Properties} for 188 * @return the {@link Properties} for the provided Step artifact 189 */ 190 public Properties getStepArtifactProperties(String stepName, String artifactName) { 191 Properties properties = new Properties(); 192 properties.putAll(getStepProperties(stepName)); 193 194 Map<String, Properties> artifactProperties = stepArtifactProperties.get(stepName); 195 196 if (artifactProperties != null && artifactProperties.containsKey(artifactName)) { 197 properties.putAll(artifactProperties.get(artifactName)); 198 } 199 200 if(stepName.contains(PARTITION_INDICATOR)) { 201 String parentStepName = stepName.substring(0, stepName.indexOf(PARTITION_INDICATOR)); 202 properties.putAll(getStepProperties(parentStepName)); 203 204 Map<String, Properties> parentArtifactProperties = stepArtifactProperties.get(parentStepName); 205 206 if (parentArtifactProperties != null && parentArtifactProperties.containsKey(artifactName)) { 207 properties.putAll(parentArtifactProperties.get(artifactName)); 208 } 209 } 210 211 return properties; 212 } 213 214 /** 215 * <p> 216 * Adds Step artifact properties to the context. 217 * </p> 218 * 219 * @param properties the step artifact {@link Properties} to add 220 */ 221 @SuppressWarnings("serial") 222 public void setStepArtifactProperties(Map<String, Map<String, Properties>> properties) { 223 Assert.notNull(properties, "Step artifact properties cannot be null"); 224 225 for(Map.Entry<String, Map<String, Properties>> propertyEntries : properties.entrySet()) { 226 String stepName = propertyEntries.getKey(); 227 228 for(Map.Entry<String, Properties> artifactEntries : propertyEntries.getValue().entrySet()) { 229 final String artifactName = artifactEntries.getKey(); 230 final Properties props = artifactEntries.getValue(); 231 232 Map<String, Properties> artifactProperties = stepArtifactProperties.get(stepName); 233 234 if (artifactProperties == null) { 235 stepArtifactProperties.put(stepName, new HashMap<String, Properties>() {{ 236 put(artifactName, props); 237 }}); 238 } else { 239 artifactProperties.put(artifactName, props); 240 } 241 } 242 } 243 } 244}