/** * Parse a single line order. * * <p>Null arguments are not permitted, except for phaseType. If phaseType is * Phase.PhaseType.RETREAT, "Move" format orders will be made into Retreat orders, and convoyed * moves will be disallowed. */ public NJudgeOrder parse( final dip.world.Map map, final OrderFactory orderFactory, final Phase.PhaseType phaseType, final String line) throws OrderException { // create order parsing context final ParseContext pc = new ParseContext(map, orderFactory, phaseType, line); // parse results. This also removes the trailing '.' from the order final ArrayList resultList = new ArrayList(5); final String newOrderLine = removeTrailingDot(parseResults(pc, resultList)); if (Phase.PhaseType.ADJUSTMENT.equals(phaseType)) { return parseAdjustmentOrder(pc, newOrderLine); } else { // tokenize order final String[] tokens = tokenize(newOrderLine); // parse order prefix OrderPrefix prefix = new OrderPrefix(pc, tokens); // parse predicate Orderable order = parsePredicate(pc, prefix, tokens); // parse text results into real results List results = createResults(pc, order, resultList); // create NJudgeOrder return new NJudgeOrder(order, results, pc.isAdjustmentPhase()); } } // parse()
private NJudgeOrder parseAdjustmentOrder(ParseContext pc, String line) throws OrderException { Matcher m = ADJUSTMENT_PATTERN.matcher(line); // attempt if (m.find()) { /* Groups: 1: Power 2: remove|build|default (default is also a remove!) 3: fleet|army|wing 4: location */ // parse power final Power power = parsePower(pc, m.group(1).trim()); // parse unit type final Unit.Type unit = parseUnitType(pc, m.group(3)); // parse location final Location location = parseLocation(pc, m.group(4).trim()); // parse action final boolean isDefault = ("default".equalsIgnoreCase(m.group(2))); Orderable order = null; if ("build".equalsIgnoreCase(m.group(2))) { order = pc.orderFactory.createBuild(power, location, unit); } else { // remove or default order = pc.orderFactory.createRemove(power, location, unit); } NJudgeOrder njo = null; if (isDefault) { // power defaulted; order is contained in a substitutedResult SubstitutedResult substResult = new SubstitutedResult(null, order, "Power defaulted; unit removed."); njo = new NJudgeOrder(null, substResult, pc.isAdjustmentPhase()); } else { njo = new NJudgeOrder( order, new OrderResult(order, OrderResult.ResultType.SUCCESS, null), pc.isAdjustmentPhase()); } assert (njo != null); return njo; } else { // reuse variable 'm' m = ALTERNATE_ADJUSTMENT_PATTERN.matcher(line); if (m.find()) { // parse power final Power power = parsePower(pc, m.group(1).trim()); // parse # (may be empty) // (if it is empty, set to 0) int numBuilds = 0; try { if (m.group(2).length() >= 1) { numBuilds = Integer.parseInt(m.group(2)); } } catch (NumberFormatException e) { throw new OrderException( "Expected valid integer at \"" + m.group(2) + "\" for order: " + pc.orderText); } // parse if unused/unusable boolean isUnusable = false; final String group3Tok = m.group(3); if ("unused".equalsIgnoreCase(group3Tok) || "unusable".equalsIgnoreCase(group3Tok)) { isUnusable = true; } // parse if pending/waived final boolean isPending = "pending".equalsIgnoreCase(m.group(5)); final boolean isWaived = "waived".equalsIgnoreCase(m.group(5)); if (m.group(3) == null) { // Group3 is null when it is a 'regular' waive order. Result result = new Result(power, "Build waived."); return new NJudgeOrder(power, result); } else { // since we depend on external input, these should // be exceptions rather than asserts // assert (isUnusable); if (!isUnusable) { throw new IllegalStateException(); } assert (isPending != isWaived); if (isPending == isWaived) { throw new IllegalStateException(); } if (isPending) { // pending builds Result result = new Result(power, String.valueOf(numBuilds) + " unusable build(s) pending."); return new NJudgeOrder(power, numBuilds, 0, result); } else { // waived builds Result result = new Result(power, String.valueOf(numBuilds) + " unusable build(s) waived."); return new NJudgeOrder(power, 0, numBuilds, result); } } } else { throw new OrderException("Cannot parse adjustment order: " + pc.orderText); } } } // parseAdjustmentOrder()