View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.xml.ingest;
17  
18  import static com.google.common.base.Preconditions.checkArgument;
19  import static com.google.common.base.Preconditions.checkNotNull;
20  import static com.google.common.base.Preconditions.checkState;
21  
22  import org.apache.commons.lang3.StringUtils;
23  import org.kuali.common.util.log.LoggerUtils;
24  import org.kuali.common.util.runonce.smart.RunOnce;
25  import org.kuali.common.util.runonce.smart.RunOnceState;
26  import org.kuali.rice.core.api.util.Truth;
27  import org.kuali.rice.coreservice.api.parameter.Parameter;
28  import org.kuali.rice.coreservice.api.parameter.ParameterType;
29  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
30  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
31  import org.slf4j.Logger;
32  
33  import com.google.common.base.Optional;
34  
35  public final class ParameterServiceRunOnce implements RunOnce {
36  
37  	private static final Logger logger = LoggerUtils.make();
38  
39  	private final String applicationId;
40  	private final String namespace;
41  	private final String component;
42  	private final String name;
43  	private final Optional<String> description;
44  	private final boolean runOnMissingParameter;
45  
46  	//
47  	private boolean initialized = false;
48  	private boolean runonce = false;
49  	private ParameterService service;
50  
51  	private static final String CONFIGURATION_PARAMETER_TYPE = "CONFG";
52  	private static final String YES = "Y";
53  
54  	@Override
55  	public synchronized void initialize() {
56  		checkState(!initialized, "Already initialized");
57  		this.service = CoreFrameworkServiceLocator.getParameterService();
58  		Optional<Parameter> parameter = Optional.fromNullable(service.getParameter(namespace, component, name));
59  		if (!parameter.isPresent() && runOnMissingParameter) {
60  			parameter = Optional.of(createParameter());
61  		}
62  		this.runonce = isRunOnce(parameter);
63  		showConfig(parameter);
64  		this.initialized = true;
65  	}
66  
67  	@Override
68  	public synchronized boolean isTrue() {
69  		checkState(initialized, "Not initialized");
70  		return runonce;
71  	}
72  
73  	@Override
74  	public synchronized void changeState(RunOnceState state) {
75  		// Ensure things are as they should be
76  		checkState(initialized, "Not initialized");
77  		checkNotNull(state, "'state' cannot be null");
78  
79  		// Get the existing parameter
80  		Parameter existingParameter = service.getParameter(namespace, component, name);
81  
82  		// Can't change the state of a non-existent parameter
83  		// The isRunOnce() method called during initialization cannot return true unless a parameter exists and it's value is set to 'Y'
84  		checkNotNull(existingParameter, "'existingParameter' cannot be null");
85  
86  		// Update the parameter
87  		logger.info("Updating parameter: [{}]", name);
88  		Parameter.Builder builder = Parameter.Builder.create(existingParameter);
89  		builder.setValue(state.name());
90  		Parameter updatedParameter = service.updateParameter(builder.build());
91  
92  		// This must always return false here
93  		this.runonce = isRunOnce(updatedParameter);
94  		checkState(!isTrue(), "isTrue() must return false");
95  
96  		// Emit a log message indicating the change in state
97  		logger.info("Transitioned RunOnce to - [{}]", updatedParameter.getValue());
98  	}
99  
100 	protected boolean isRunOnce(Optional<Parameter> parameter) {
101 		if (parameter.isPresent()) {
102 			return isRunOnce(parameter.get());
103 		} else {
104 			return false;
105 		}
106 	}
107 
108 	protected boolean isRunOnce(Parameter parameter) {
109 		return Boolean.parseBoolean(Truth.strToBooleanIgnoreCase(parameter.getValue()) + "");
110 	}
111 
112 	protected Parameter createParameter() {
113 		logger.info("Creating parameter: [{}]=[{}]", name, YES);
114 		Parameter.Builder builder = Parameter.Builder.create(applicationId, namespace, component, name, ParameterType.Builder.create(CONFIGURATION_PARAMETER_TYPE));
115 		builder.setValue(YES);
116 		if (description.isPresent()) {
117 			builder.setDescription(description.get());
118 		}
119 		return service.createParameter(builder.build());
120 	}
121 
122 	protected void showConfig(Optional<Parameter> optional) {
123 		logger.info(String.format("Parameter Metadata: [%s:%s:%s]", applicationId, namespace, component));
124 		if (optional.isPresent()) {
125 			Parameter parameter = optional.get();
126 			logger.info("Parameter: [{}]=[{}]", name, parameter.getValue());
127 		} else {
128 			logger.info("Parameter [{}] does not exist", name);
129 		}
130 		logger.info("RunOnce: [{}]", runonce);
131 	}
132 
133 	private ParameterServiceRunOnce(Builder builder) {
134 		this.applicationId = builder.applicationId;
135 		this.namespace = builder.namespace;
136 		this.component = builder.component;
137 		this.name = builder.name;
138 		this.description = builder.description;
139 		this.runOnMissingParameter = builder.runOnMissingParameter;
140 	}
141 
142 	public static Builder builder() {
143 		return new Builder();
144 	}
145 
146 	public static class Builder {
147 
148 		private String applicationId;
149 		private String namespace;
150 		private String component;
151 		private String name;
152 		private Optional<String> description;
153 		private boolean runOnMissingParameter;
154 
155 		public Builder runOnMissingParameter(boolean runOnMissingParameter) {
156 			this.runOnMissingParameter = runOnMissingParameter;
157 			return this;
158 		}
159 
160 		public Builder applicationId(String applicationId) {
161 			this.applicationId = applicationId;
162 			return this;
163 		}
164 
165 		public Builder namespace(String namespace) {
166 			this.namespace = namespace;
167 			return this;
168 		}
169 
170 		public Builder component(String component) {
171 			this.component = component;
172 			return this;
173 		}
174 
175 		public Builder name(String name) {
176 			this.name = name;
177 			return this;
178 		}
179 
180 		public Builder description(String name) {
181 			this.description = Optional.fromNullable(name);
182 			return this;
183 		}
184 
185 		public ParameterServiceRunOnce build() {
186 			ParameterServiceRunOnce instance = new ParameterServiceRunOnce(this);
187 			validate(instance);
188 			return instance;
189 		}
190 
191 		private static void validate(ParameterServiceRunOnce instance) {
192 			checkArgument(!StringUtils.isBlank(instance.getApplicationId()), "'application' id cannot be null");
193 			checkArgument(!StringUtils.isBlank(instance.getNamespace()), "'namespace' cannot be null");
194 			checkArgument(!StringUtils.isBlank(instance.getComponent()), "'component' cannot be null");
195 			checkArgument(!StringUtils.isBlank(instance.getName()), "'name' cannot be null");
196 			checkNotNull(instance.description, "'description' cannot be null");
197 		}
198 
199 		public String getApplicationId() {
200 			return applicationId;
201 		}
202 
203 		public void setApplicationId(String applicationId) {
204 			this.applicationId = applicationId;
205 		}
206 
207 		public String getNamespace() {
208 			return namespace;
209 		}
210 
211 		public void setNamespace(String namespace) {
212 			this.namespace = namespace;
213 		}
214 
215 		public String getComponent() {
216 			return component;
217 		}
218 
219 		public void setComponent(String component) {
220 			this.component = component;
221 		}
222 
223 		public String getName() {
224 			return name;
225 		}
226 
227 		public void setName(String name) {
228 			this.name = name;
229 		}
230 
231 		public Optional<String> getDescription() {
232 			return description;
233 		}
234 
235 		public void setDescription(Optional<String> description) {
236 			this.description = description;
237 		}
238 
239 	}
240 
241 	public String getApplicationId() {
242 		return applicationId;
243 	}
244 
245 	public String getNamespace() {
246 		return namespace;
247 	}
248 
249 	public String getComponent() {
250 		return component;
251 	}
252 
253 	public String getName() {
254 		return name;
255 	}
256 
257 	public Optional<String> getDescription() {
258 		return description;
259 	}
260 
261 	public boolean isRunOnMissingParameter() {
262 		return runOnMissingParameter;
263 	}
264 
265 }