This project has retired. For details please refer to its
Attic page.
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, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.oozie.command.coord;
019
020 import java.io.StringReader;
021 import java.net.URI;
022 import java.util.Calendar;
023 import java.util.Date;
024 import java.util.HashMap;
025 import java.util.List;
026 import java.util.Map;
027
028 import org.apache.hadoop.conf.Configuration;
029 import org.apache.oozie.CoordinatorActionBean;
030 import org.apache.oozie.ErrorCode;
031 import org.apache.oozie.client.CoordinatorAction;
032 import org.apache.oozie.command.CommandException;
033 import org.apache.oozie.coord.CoordELEvaluator;
034 import org.apache.oozie.coord.CoordELFunctions;
035 import org.apache.oozie.coord.CoordUtils;
036 import org.apache.oozie.coord.CoordinatorJobException;
037 import org.apache.oozie.coord.SyncCoordAction;
038 import org.apache.oozie.coord.TimeUnit;
039 import org.apache.oozie.dependency.ActionDependency;
040 import org.apache.oozie.dependency.DependencyChecker;
041 import org.apache.oozie.dependency.URIHandler;
042 import org.apache.oozie.dependency.URIHandler.DependencyType;
043 import org.apache.oozie.service.Services;
044 import org.apache.oozie.service.URIHandlerService;
045 import org.apache.oozie.service.UUIDService;
046 import org.apache.oozie.util.DateUtils;
047 import org.apache.oozie.util.ELEvaluator;
048 import org.apache.oozie.util.XConfiguration;
049 import org.apache.oozie.util.XmlUtils;
050 import org.jdom.Element;
051
052 public class CoordCommandUtils {
053 public static int CURRENT = 0;
054 public static int LATEST = 1;
055 public static int FUTURE = 2;
056 public static int OFFSET = 3;
057 public static int UNEXPECTED = -1;
058 public static final String RESOLVED_UNRESOLVED_SEPARATOR = "!!";
059 public static final String UNRESOLVED_INST_TAG = "unresolved-instances";
060
061 /**
062 * parse a function like coord:latest(n)/future() and return the 'n'.
063 * <p/>
064 *
065 * @param function
066 * @param restArg
067 * @return int instanceNumber
068 * @throws Exception
069 */
070 public static int getInstanceNumber(String function, StringBuilder restArg) throws Exception {
071 int funcType = getFuncType(function);
072 if (funcType == CURRENT || funcType == LATEST) {
073 return parseOneArg(function);
074 }
075 else {
076 return parseMoreArgs(function, restArg);
077 }
078 }
079
080 /**
081 * Evaluates function for coord-action-create-inst tag
082 * @param event
083 * @param appInst
084 * @param conf
085 * @param function
086 * @return evaluation result
087 * @throws Exception
088 */
089 private static String evaluateInstanceFunction(Element event, SyncCoordAction appInst, Configuration conf,
090 String function) throws Exception {
091 ELEvaluator eval = CoordELEvaluator.createInstancesELEvaluator("coord-action-create-inst", event, appInst, conf);
092 return CoordELFunctions.evalAndWrap(eval, function);
093 }
094
095 public static int parseOneArg(String funcName) throws Exception {
096 int firstPos = funcName.indexOf("(");
097 int lastPos = funcName.lastIndexOf(")");
098 if (firstPos >= 0 && lastPos > firstPos) {
099 String tmp = funcName.substring(firstPos + 1, lastPos).trim();
100 if (tmp.length() > 0) {
101 return (int) Double.parseDouble(tmp);
102 }
103 }
104 throw new RuntimeException("Unformatted function :" + funcName);
105 }
106
107 private static int parseMoreArgs(String funcName, StringBuilder restArg) throws Exception {
108 int firstPos = funcName.indexOf("(");
109 int secondPos = funcName.lastIndexOf(",");
110 int lastPos = funcName.lastIndexOf(")");
111 if (firstPos >= 0 && secondPos > firstPos) {
112 String tmp = funcName.substring(firstPos + 1, secondPos).trim();
113 if (tmp.length() > 0) {
114 restArg.append(funcName.substring(secondPos + 1, lastPos).trim());
115 return (int) Double.parseDouble(tmp);
116 }
117 }
118 throw new RuntimeException("Unformatted function :" + funcName);
119 }
120
121 /**
122 * @param EL function name
123 * @return type of EL function
124 */
125 public static int getFuncType(String function) {
126 if (function.indexOf("current") >= 0) {
127 return CURRENT;
128 }
129 else if (function.indexOf("latest") >= 0) {
130 return LATEST;
131 }
132 else if (function.indexOf("future") >= 0) {
133 return FUTURE;
134 }
135 else if (function.indexOf("offset") >= 0) {
136 return OFFSET;
137 }
138 return UNEXPECTED;
139 // throw new RuntimeException("Unexpected instance name "+ function);
140 }
141
142 /**
143 * @param startInst: EL function name
144 * @param endInst: EL function name
145 * @throws CommandException if both are not the same function
146 */
147 public static void checkIfBothSameType(String startInst, String endInst) throws CommandException {
148 if (getFuncType(startInst) != getFuncType(endInst)) {
149 throw new CommandException(ErrorCode.E1010,
150 " start-instance and end-instance both should be either latest or current or future or offset\n"
151 + " start " + startInst + " and end " + endInst);
152 }
153 }
154
155 /**
156 * Resolve list of <instance> </instance> tags.
157 *
158 * @param event
159 * @param instances
160 * @param actionInst
161 * @param conf
162 * @param eval: ELEvalautor
163 * @throws Exception
164 */
165 public static void resolveInstances(Element event, StringBuilder instances, SyncCoordAction actionInst,
166 Configuration conf, ELEvaluator eval) throws Exception {
167 for (Element eInstance : (List<Element>) event.getChildren("instance", event.getNamespace())) {
168 if (instances.length() > 0) {
169 instances.append(CoordELFunctions.INSTANCE_SEPARATOR);
170 }
171 instances.append(materializeInstance(event, eInstance.getTextTrim(), actionInst, conf, eval));
172 }
173 event.removeChildren("instance", event.getNamespace());
174 }
175
176 /**
177 * Resolve <start-instance> <end-insatnce> tag. Don't resolve any
178 * latest()/future()
179 *
180 * @param event
181 * @param instances
182 * @param appInst
183 * @param conf
184 * @param eval: ELEvalautor
185 * @throws Exception
186 */
187 public static void resolveInstanceRange(Element event, StringBuilder instances, SyncCoordAction appInst,
188 Configuration conf, ELEvaluator eval) throws Exception {
189 Element eStartInst = event.getChild("start-instance", event.getNamespace());
190 Element eEndInst = event.getChild("end-instance", event.getNamespace());
191 if (eStartInst != null && eEndInst != null) {
192 String strStart = evaluateInstanceFunction(event, appInst, conf, eStartInst.getTextTrim());
193 String strEnd = evaluateInstanceFunction(event, appInst, conf, eEndInst.getTextTrim());
194 checkIfBothSameType(strStart, strEnd);
195 StringBuilder restArg = new StringBuilder(); // To store rest
196 // arguments for
197 // future
198 // function
199 int startIndex = getInstanceNumber(strStart, restArg);
200 String startRestArg = restArg.toString();
201 restArg.delete(0, restArg.length());
202 int endIndex = getInstanceNumber(strEnd, restArg);
203 String endRestArg = restArg.toString();
204 int funcType = getFuncType(strStart);
205 if (funcType == OFFSET) {
206 TimeUnit startU = TimeUnit.valueOf(startRestArg);
207 TimeUnit endU = TimeUnit.valueOf(endRestArg);
208 if (startU.getCalendarUnit() * startIndex > endU.getCalendarUnit() * endIndex) {
209 throw new CommandException(ErrorCode.E1010,
210 " start-instance should be equal or earlier than the end-instance \n"
211 + XmlUtils.prettyPrint(event));
212 }
213 Calendar startCal = CoordELFunctions.resolveOffsetRawTime(startIndex, startU, eval);
214 Calendar endCal = CoordELFunctions.resolveOffsetRawTime(endIndex, endU, eval);
215 if (startCal != null && endCal != null) {
216 List<Integer> expandedFreqs = CoordELFunctions.expandOffsetTimes(startCal, endCal, eval);
217 for (int i = expandedFreqs.size() - 1; i >= 0; i--) {
218 String matInstance = materializeInstance(event, "${coord:offset(" + expandedFreqs.get(i)
219 + ", \"MINUTE\")}", appInst, conf, eval);
220 if (matInstance == null || matInstance.length() == 0) {
221 // Earlier than dataset's initial instance
222 break;
223 }
224 if (instances.length() > 0) {
225 instances.append(CoordELFunctions.INSTANCE_SEPARATOR);
226 }
227 instances.append(matInstance);
228 }
229 }
230 }
231 else {
232 if (startIndex > endIndex) {
233 throw new CommandException(ErrorCode.E1010,
234 " start-instance should be equal or earlier than the end-instance \n"
235 + XmlUtils.prettyPrint(event));
236 }
237 if (funcType == CURRENT) {
238 // Everything could be resolved NOW. no latest() ELs
239 String matInstance = materializeInstance(event, "${coord:currentRange(" + startIndex + ","
240 + endIndex + ")}", appInst, conf, eval);
241 if (matInstance != null && !matInstance.isEmpty()) {
242 if (instances.length() > 0) {
243 instances.append(CoordELFunctions.INSTANCE_SEPARATOR);
244 }
245 instances.append(matInstance);
246 }
247 }
248 else { // latest(n)/future() EL is present
249 if (funcType == LATEST) {
250 instances.append("${coord:latestRange(").append(startIndex).append(",").append(endIndex)
251 .append(")}");
252 }
253 else if (funcType == FUTURE) {
254 instances.append("${coord:futureRange(").append(startIndex).append(",").append(endIndex)
255 .append(",'").append(endRestArg).append("')}");
256 }
257 }
258 }
259 // Remove start-instance and end-instances
260 event.removeChild("start-instance", event.getNamespace());
261 event.removeChild("end-instance", event.getNamespace());
262 }
263 }
264
265 /**
266 * Materialize one instance like current(-2)
267 *
268 * @param event : <data-in>
269 * @param expr : instance like current(-1)
270 * @param appInst : application specific info
271 * @param conf
272 * @param evalInst :ELEvaluator
273 * @return materialized date string
274 * @throws Exception
275 */
276 public static String materializeInstance(Element event, String expr, SyncCoordAction appInst, Configuration conf,
277 ELEvaluator evalInst) throws Exception {
278 if (event == null) {
279 return null;
280 }
281 // ELEvaluator eval = CoordELEvaluator.createInstancesELEvaluator(event,
282 // appInst, conf);
283 return CoordELFunctions.evalAndWrap(evalInst, expr);
284 }
285
286 /**
287 * Create two new tags with <uris> and <unresolved-instances>.
288 *
289 * @param event
290 * @param instances
291 * @throws Exception
292 */
293 private static String separateResolvedAndUnresolved(Element event, StringBuilder instances)
294 throws Exception {
295 StringBuilder unresolvedInstances = new StringBuilder();
296 StringBuilder urisWithDoneFlag = new StringBuilder();
297 StringBuilder depList = new StringBuilder();
298 String uris = createEarlyURIs(event, instances.toString(), unresolvedInstances, urisWithDoneFlag);
299 if (uris.length() > 0) {
300 Element uriInstance = new Element("uris", event.getNamespace());
301 uriInstance.addContent(uris);
302 event.getContent().add(1, uriInstance);
303 if (depList.length() > 0) {
304 depList.append(CoordELFunctions.INSTANCE_SEPARATOR);
305 }
306 depList.append(urisWithDoneFlag);
307 }
308 if (unresolvedInstances.length() > 0) {
309 Element elemInstance = new Element(UNRESOLVED_INST_TAG, event.getNamespace());
310 elemInstance.addContent(unresolvedInstances.toString());
311 event.getContent().add(1, elemInstance);
312 }
313 return depList.toString();
314 }
315
316 /**
317 * The function create a list of URIs separated by "," using the instances
318 * time stamp and URI-template
319 *
320 * @param event : <data-in> event
321 * @param instances : List of time stamp separated by ","
322 * @param unresolvedInstances : list of instance with latest function
323 * @param urisWithDoneFlag : list of URIs with the done flag appended
324 * @return : list of URIs separated by ";" as a string.
325 * @throws Exception
326 */
327 public static String createEarlyURIs(Element event, String instances, StringBuilder unresolvedInstances,
328 StringBuilder urisWithDoneFlag) throws Exception {
329 if (instances == null || instances.length() == 0) {
330 return "";
331 }
332 String[] instanceList = instances.split(CoordELFunctions.INSTANCE_SEPARATOR);
333 StringBuilder uris = new StringBuilder();
334
335 Element doneFlagElement = event.getChild("dataset", event.getNamespace()).getChild("done-flag",
336 event.getNamespace());
337 URIHandlerService uriService = Services.get().get(URIHandlerService.class);
338
339 for (int i = 0; i < instanceList.length; i++) {
340 if (instanceList[i].trim().length() == 0) {
341 continue;
342 }
343 int funcType = getFuncType(instanceList[i]);
344 if (funcType == LATEST || funcType == FUTURE) {
345 if (unresolvedInstances.length() > 0) {
346 unresolvedInstances.append(CoordELFunctions.INSTANCE_SEPARATOR);
347 }
348 unresolvedInstances.append(instanceList[i]);
349 continue;
350 }
351 ELEvaluator eval = CoordELEvaluator.createURIELEvaluator(instanceList[i]);
352 if (uris.length() > 0) {
353 uris.append(CoordELFunctions.INSTANCE_SEPARATOR);
354 urisWithDoneFlag.append(CoordELFunctions.INSTANCE_SEPARATOR);
355 }
356
357 String uriPath = CoordELFunctions.evalAndWrap(eval, event.getChild("dataset", event.getNamespace())
358 .getChild("uri-template", event.getNamespace()).getTextTrim());
359 URIHandler uriHandler = uriService.getURIHandler(uriPath);
360 uriHandler.validate(uriPath);
361 uris.append(uriPath);
362 urisWithDoneFlag.append(uriHandler.getURIWithDoneFlag(uriPath, CoordUtils.getDoneFlag(doneFlagElement)));
363 }
364 return uris.toString();
365 }
366
367 /**
368 * @param eSla
369 * @param nominalTime
370 * @param conf
371 * @return boolean to determine whether the SLA element is present or not
372 * @throws CoordinatorJobException
373 */
374 public static boolean materializeSLA(Element eSla, Date nominalTime, Configuration conf)
375 throws CoordinatorJobException {
376 if (eSla == null) {
377 // eAppXml.getNamespace("sla"));
378 return false;
379 }
380 try {
381 ELEvaluator evalSla = CoordELEvaluator.createSLAEvaluator(nominalTime, conf);
382 List<Element> elemList = eSla.getChildren();
383 for (Element elem : elemList) {
384 String updated;
385 try {
386 updated = CoordELFunctions.evalAndWrap(evalSla, elem.getText().trim());
387 }
388 catch (Exception e) {
389 throw new CoordinatorJobException(ErrorCode.E1004, e.getMessage(), e);
390 }
391 elem.removeContent();
392 elem.addContent(updated);
393 }
394 }
395 catch (Exception e) {
396 throw new CoordinatorJobException(ErrorCode.E1004, e.getMessage(), e);
397 }
398 return true;
399 }
400
401 /**
402 * Materialize one instance for specific nominal time. It includes: 1.
403 * Materialize data events (i.e. <data-in> and <data-out>) 2. Materialize
404 * data properties (i.e dataIn(<DS>) and dataOut(<DS>) 3. remove 'start' and
405 * 'end' tag 4. Add 'instance_number' and 'nominal-time' tag
406 *
407 * @param jobId coordinator job id
408 * @param dryrun true if it is dryrun
409 * @param eAction frequency unexploded-job
410 * @param nominalTime materialization time
411 * @param actualTime action actual time
412 * @param instanceCount instance numbers
413 * @param conf job configuration
414 * @param actionBean CoordinatorActionBean to materialize
415 * @return one materialized action for specific nominal time
416 * @throws Exception
417 */
418 @SuppressWarnings("unchecked")
419 public static String materializeOneInstance(String jobId, boolean dryrun, Element eAction, Date nominalTime,
420 Date actualTime, int instanceCount, Configuration conf, CoordinatorActionBean actionBean) throws Exception {
421 String actionId = Services.get().get(UUIDService.class).generateChildId(jobId, instanceCount + "");
422 SyncCoordAction appInst = new SyncCoordAction();
423 appInst.setActionId(actionId);
424 appInst.setName(eAction.getAttributeValue("name"));
425 appInst.setNominalTime(nominalTime);
426 appInst.setActualTime(actualTime);
427 int frequency = Integer.parseInt(eAction.getAttributeValue("frequency"));
428 appInst.setFrequency(frequency);
429 appInst.setTimeUnit(TimeUnit.valueOf(eAction.getAttributeValue("freq_timeunit")));
430 appInst.setTimeZone(DateUtils.getTimeZone(eAction.getAttributeValue("timezone")));
431 appInst.setEndOfDuration(TimeUnit.valueOf(eAction.getAttributeValue("end_of_duration")));
432
433 Map<String, StringBuilder> dependencyMap = null;
434
435 Element inputList = eAction.getChild("input-events", eAction.getNamespace());
436 List<Element> dataInList = null;
437 if (inputList != null) {
438 dataInList = inputList.getChildren("data-in", eAction.getNamespace());
439 dependencyMap = materializeDataEvents(dataInList, appInst, conf);
440 }
441
442 Element outputList = eAction.getChild("output-events", eAction.getNamespace());
443 List<Element> dataOutList = null;
444 if (outputList != null) {
445 dataOutList = outputList.getChildren("data-out", eAction.getNamespace());
446 materializeDataEvents(dataOutList, appInst, conf);
447 }
448
449 eAction.removeAttribute("start");
450 eAction.removeAttribute("end");
451 eAction.setAttribute("instance-number", Integer.toString(instanceCount));
452 eAction.setAttribute("action-nominal-time", DateUtils.formatDateOozieTZ(nominalTime));
453 eAction.setAttribute("action-actual-time", DateUtils.formatDateOozieTZ(actualTime));
454
455 boolean isSla = CoordCommandUtils.materializeSLA(
456 eAction.getChild("action", eAction.getNamespace()).getChild("info", eAction.getNamespace("sla")),
457 nominalTime, conf);
458
459 // Setting up action bean
460 actionBean.setCreatedConf(XmlUtils.prettyPrint(conf).toString());
461 actionBean.setRunConf(XmlUtils.prettyPrint(conf).toString());
462 actionBean.setCreatedTime(actualTime);
463 actionBean.setJobId(jobId);
464 actionBean.setId(actionId);
465 actionBean.setLastModifiedTime(new Date());
466 actionBean.setStatus(CoordinatorAction.Status.WAITING);
467 actionBean.setActionNumber(instanceCount);
468 if (dependencyMap != null) {
469 StringBuilder sbPull = dependencyMap.get(DependencyType.PULL.name());
470 if (sbPull != null) {
471 actionBean.setMissingDependencies(sbPull.toString());
472 }
473 StringBuilder sbPush = dependencyMap.get(DependencyType.PUSH.name());
474 if (sbPush != null) {
475 actionBean.setPushMissingDependencies(sbPush.toString());
476 }
477 }
478 actionBean.setNominalTime(nominalTime);
479 if (isSla == true) {
480 actionBean.setSlaXml(XmlUtils.prettyPrint(
481 eAction.getChild("action", eAction.getNamespace()).getChild("info", eAction.getNamespace("sla")))
482 .toString());
483 }
484
485 // actionBean.setTrackerUri(trackerUri);//TOOD:
486 // actionBean.setConsoleUrl(consoleUrl); //TODO:
487 // actionBean.setType(type);//TODO:
488 // actionBean.setErrorInfo(errorCode, errorMessage); //TODO:
489 // actionBean.setExternalStatus(externalStatus);//TODO
490 if (!dryrun) {
491 return XmlUtils.prettyPrint(eAction).toString();
492 }
493 else {
494 return dryRunCoord(eAction, actionBean);
495 }
496 }
497
498 /**
499 * @param eAction the actionXml related element
500 * @param actionBean the coordinator action bean
501 * @return
502 * @throws Exception
503 */
504 static String dryRunCoord(Element eAction, CoordinatorActionBean actionBean) throws Exception {
505 String action = XmlUtils.prettyPrint(eAction).toString();
506 StringBuilder actionXml = new StringBuilder(action);
507 Configuration actionConf = new XConfiguration(new StringReader(actionBean.getRunConf()));
508
509 boolean isPushDepAvailable = true;
510 if (actionBean.getPushMissingDependencies() != null) {
511 ActionDependency actionDep = DependencyChecker.checkForAvailability(
512 actionBean.getPushMissingDependencies(), actionConf, true);
513 if (actionDep.getMissingDependencies().size() != 0) {
514 isPushDepAvailable = false;
515 }
516
517 }
518 boolean isPullDepAvailable = true;
519 CoordActionInputCheckXCommand coordActionInput = new CoordActionInputCheckXCommand(actionBean.getId(),
520 actionBean.getJobId());
521 if (actionBean.getMissingDependencies() != null) {
522 StringBuilder existList = new StringBuilder();
523 StringBuilder nonExistList = new StringBuilder();
524 StringBuilder nonResolvedList = new StringBuilder();
525 getResolvedList(actionBean.getMissingDependencies(), nonExistList, nonResolvedList);
526 isPullDepAvailable = coordActionInput.checkInput(actionXml, existList, nonExistList, actionConf);
527 }
528
529 if (isPullDepAvailable && isPushDepAvailable) {
530 // Check for latest/future
531 boolean isLatestFutureDepAvailable = coordActionInput.checkUnResolvedInput(actionXml, actionConf);
532 if (isLatestFutureDepAvailable) {
533 String newActionXml = CoordActionInputCheckXCommand.resolveCoordConfiguration(actionXml, actionConf,
534 actionBean.getId());
535 actionXml.replace(0, actionXml.length(), newActionXml);
536 }
537 }
538
539 return actionXml.toString();
540 }
541
542 /**
543 * Materialize all <input-events>/<data-in> or <output-events>/<data-out>
544 * tags Create uris for resolved instances. Create unresolved instance for
545 * latest()/future().
546 *
547 * @param events
548 * @param appInst
549 * @param conf
550 * @throws Exception
551 */
552 public static Map<String, StringBuilder> materializeDataEvents(List<Element> events, SyncCoordAction appInst, Configuration conf
553 ) throws Exception {
554
555 if (events == null) {
556 return null;
557 }
558 StringBuilder unresolvedList = new StringBuilder();
559 Map<String, StringBuilder> dependencyMap = new HashMap<String, StringBuilder>();
560 URIHandlerService uriService = Services.get().get(URIHandlerService.class);
561 StringBuilder pullMissingDep = null;
562 StringBuilder pushMissingDep = null;
563
564 for (Element event : events) {
565 StringBuilder instances = new StringBuilder();
566 ELEvaluator eval = CoordELEvaluator.createInstancesELEvaluator(event, appInst, conf);
567 // Handle list of instance tag
568 resolveInstances(event, instances, appInst, conf, eval);
569 // Handle start-instance and end-instance
570 resolveInstanceRange(event, instances, appInst, conf, eval);
571 // Separate out the unresolved instances
572 String resolvedList = separateResolvedAndUnresolved(event, instances);
573 if (!resolvedList.isEmpty()) {
574 Element uri = event.getChild("dataset", event.getNamespace()).getChild("uri-template",
575 event.getNamespace());
576 String uriTemplate = uri.getText();
577 URI baseURI = uriService.getAuthorityWithScheme(uriTemplate);
578 URIHandler handler = uriService.getURIHandler(baseURI);
579 if (handler.getDependencyType(baseURI).equals(DependencyType.PULL)) {
580 pullMissingDep = (pullMissingDep == null) ? new StringBuilder(resolvedList) : pullMissingDep.append(
581 CoordELFunctions.INSTANCE_SEPARATOR).append(resolvedList);
582 }
583 else {
584 pushMissingDep = (pushMissingDep == null) ? new StringBuilder(resolvedList) : pushMissingDep.append(
585 CoordELFunctions.INSTANCE_SEPARATOR).append(resolvedList);
586 }
587 }
588
589 String tmpUnresolved = event.getChildTextTrim(UNRESOLVED_INST_TAG, event.getNamespace());
590 if (tmpUnresolved != null) {
591 if (unresolvedList.length() > 0) {
592 unresolvedList.append(CoordELFunctions.INSTANCE_SEPARATOR);
593 }
594 unresolvedList.append(tmpUnresolved);
595 }
596 }
597 if (unresolvedList.length() > 0) {
598 if (pullMissingDep == null) {
599 pullMissingDep = new StringBuilder();
600 }
601 pullMissingDep.append(RESOLVED_UNRESOLVED_SEPARATOR).append(unresolvedList);
602 }
603 dependencyMap.put(DependencyType.PULL.name(), pullMissingDep);
604 dependencyMap.put(DependencyType.PUSH.name(), pushMissingDep);
605 return dependencyMap;
606 }
607
608 /**
609 * Get resolved string from missDepList
610 *
611 * @param missDepList
612 * @param resolved
613 * @param unresolved
614 * @return resolved string
615 */
616 public static String getResolvedList(String missDepList, StringBuilder resolved, StringBuilder unresolved) {
617 if (missDepList != null) {
618 int index = missDepList.indexOf(RESOLVED_UNRESOLVED_SEPARATOR);
619 if (index < 0) {
620 resolved.append(missDepList);
621 }
622 else {
623 resolved.append(missDepList.substring(0, index));
624 unresolved.append(missDepList.substring(index + RESOLVED_UNRESOLVED_SEPARATOR.length()));
625 }
626 }
627 return resolved.toString();
628 }
629
630 }