public List<String> generateIDs(int num) {
		if (this.updateOptions) {
			this.update();
		}

		ArrayList<String> ids = new ArrayList<String>();

		logger.info(Messages.getString("IdGenerator.START_GENERATION") + num);

		Template template = new Template(this.options.getData());

		int i = 0;
		while (template.hasAlternatives() && (ids.size() < num)) {
			if (i++ == Globals.MAX_ATTEMPTS) {
				logger.fatal(Messages.getString("IdGenerator.MAX_ATTEMPTS_REACHED") + " (" + Globals.MAX_ATTEMPTS + ")");
				System.exit(152);
			}
			String idCandidate = null;
			idCandidate = template.buildString();
			logger.trace(Messages.getString("IdGenerator.TRACE_ID_CANDIDATE") + " " + idCandidate);

			// apply the filter chain to the generated id
			// add to list if we got a valid, unique id 
			if (	(this.filterChain.apply(idCandidate) != null)
					&& (!ids.contains(idCandidate)))
			{
				ids.add(idCandidate);
			}
			else { 
				// log some info about the failed attempt 
				logger.trace(Messages.getString("IdGenerator.TRACE_ATTEMPT_GENERATE") + " " + idCandidate);
			}
		}

		logger.debug(Messages.getString("IdGenerator.NUMBER_OF_ITERATIONS") + i);

		if (ids.size() < num) {
			logger.warn(Messages.getString("IdGenerator.FAILED_TO_REACH_TARGET_NUM") + ids.size());
		}

		if (ids.size() == 0) {
			logger.fatal(Messages.getString("IdGenerator.NO_ALTERNATIVES_LEFT"));
		}

		return ids;
	}