public final Set augmentReferenceSet()

in taverna-reference-impl/src/main/java/org/apache/taverna/reference/impl/ReferenceSetAugmentorImpl.java [198:299]


	public final Set<ExternalReferenceSPI> augmentReferenceSet(
			ReferenceSet references,
			Set<Class<ExternalReferenceSPI>> targetReferenceTypes,
			ReferenceContext context) throws ReferenceSetAugmentationException {
		synchronized (this) {
			if (!cacheValid)
				update();
		}

		// Synchronize on the reference set itself
		synchronized (references) {
			/*
			 * First check whether we actually need to modify the reference set
			 * at all - it's perfectly valid to call the augmentor when nothing
			 * actually needs to be done (ideally you wouldn't do this, but it's
			 * likely to happen)
			 */
			for (ExternalReferenceSPI er : references.getExternalReferences())
				if (targetReferenceTypes.contains(er.getClass()))
					return new HashSet<>();

			// Need to perform augmentation if we reach this point
			List<TranslationPath> candidatePaths = new ArrayList<>();
			for (Class<ExternalReferenceSPI> target : targetReferenceTypes) {
				ShortestPathSolver solver = solvers.get(target);
				if (solver == null) {
					solver = new ShortestPathSolver(target);
					solvers.put(target, solver);
				}
				if (solver != null)
					for (TranslationPath path : solver.getTranslationPaths()) {
						for (ExternalReferenceSPI er : references
								.getExternalReferences())
							if (er.getClass().equals(path.getSourceType()))
								candidatePaths.add(path);
						for (TranslationPath dereferenceBasedPath : path
								.getDereferenceBasedPaths(references))
							candidatePaths.add(dereferenceBasedPath);
					}
			}
			/*
			 * Now add candidate paths to represent a no-translator 'direct from
			 * byte stream source' path for each target type compatible
			 * reference builder
			 */
			for (ExternalReferenceBuilderSPI<?> builder : builders)
				if (targetReferenceTypes.contains(builder.getReferenceType()))
					/*
					 * The builder can construct one of the target types, add
					 * paths for all possible pairs of 'de-reference existing
					 * reference' and the builder
					 */
					for (ExternalReferenceSPI er : references
							.getExternalReferences()) {
						TranslationPath newPath = new TranslationPath();
						newPath.setBuilders(builders);
						newPath.setInitialBuilder(builder);
						newPath.setSourceReference(er);
						candidatePaths.add(newPath);
					}

			/*
			 * Got a list of candidate paths sorted by estimated overall path
			 * cost
			 */
			Collections.sort(candidatePaths);
			if (log.isDebugEnabled()) {
				log.debug("Found "
						+ candidatePaths.size()
						+ " contextual translation path(s) including builder based :");
				int counter = 0;
				for (TranslationPath path : candidatePaths)
					log.debug("  " + (++counter) + ") " + path.toString());
			}

			if (candidatePaths.isEmpty()) {
				log.warn("No candidate paths found for augmentation");
				throw new ReferenceSetAugmentationException(
						"No candidate translation paths were found");
			}

			log.debug("Performing augmentation :");
			int counter = 0;
			for (TranslationPath path : candidatePaths)
				try {
					counter++;
					Set<ExternalReferenceSPI> newReferences = path
							.doTranslation(references, context);
					if (log.isDebugEnabled())
						log.debug("  Success (" + counter + "), created "
								+ printRefSet(newReferences));
					return newReferences;
				} catch (Exception ex) {
					log.debug("  Failed (" + counter + ")");
					log.trace(ex);
					// Use next path...
				}
			log.warn("  No paths succeeded, augmentation failed");
			throw new ReferenceSetAugmentationException(
					"All paths threw exceptions, can't perform augmentation");
		}
	}