001package org.clafer.scope; 002 003import java.util.HashMap; 004import java.util.Map; 005import org.clafer.ast.AstClafer; 006 007/** 008 * Builder pattern for scopes. Use {@link Scope#builder()}, 009 * {@link Scope#setScope(org.clafer.ast.AstClafer, int)}, {@link Scope#defaultScope(int)}, 010 * {@link Scope#intLow}, or {@link Scope#intHigh} to construct the builder. The 011 * default scope and lowest and highest integers will be given a default if not 012 * set explicitly. 013 * 014 * @author jimmy 015 * @see Scope 016 */ 017public class ScopeBuilder implements Scopable { 018 019 private final Map<AstClafer, Integer> scope; 020 private int defaultScope = 1; 021 private int intLow = -16; 022 private int intHigh = 16; 023 024 ScopeBuilder(Map<AstClafer, Integer> scope, int defaultScope, int intLow, int intHigh) { 025 this.scope = new HashMap<>(scope); 026 this.defaultScope = defaultScope; 027 this.intLow = intLow; 028 this.intHigh = intHigh; 029 } 030 031 ScopeBuilder() { 032 this.scope = new HashMap<>(); 033 } 034 035 /** 036 * Set the scope of the Clafer. If the scope is already set for the Clafer, 037 * then the new scope overrides the previous one. 038 * 039 * @param clafer the Clafer 040 * @param scope the scope of the clafer 041 * @return this builder 042 */ 043 public ScopeBuilder setScope(AstClafer clafer, int scope) { 044 this.scope.put(clafer, scope); 045 return this; 046 } 047 048 /** 049 * Adjust the scope of the Clafer. If the Clafer already has a scope then 050 * {@code newScope = oldScope + adjust}. Otherwise 051 * {@code newScope = defaultScope + adjust}. 052 * 053 * @param clafer the Clafer 054 * @param adjust increment the scope by this amount 055 * @return this builder 056 */ 057 public ScopeBuilder adjustScope(AstClafer clafer, int adjust) { 058 Integer oldScope = scope.get(clafer); 059 scope.put(clafer, adjust + (oldScope == null ? defaultScope : oldScope.intValue())); 060 return this; 061 } 062 063 /** 064 * Set the scope for unspecified Clafers. If the default scope is already 065 * set, then the new default scope overrides the previous one. 066 * 067 * @param defaultScope the default scope 068 * @return this builder 069 */ 070 public ScopeBuilder defaultScope(int defaultScope) { 071 this.defaultScope = defaultScope; 072 return this; 073 } 074 075 /** 076 * Adjust the scope of unspecified Clafers. 077 * 078 * @param adjust increment the default scope by this amount 079 * @return this builder 080 */ 081 public ScopeBuilder adjustDefaultScope(int adjust) { 082 defaultScope += adjust; 083 return this; 084 } 085 086 /** 087 * Set the lowest (inclusive) integer used for solving. If the lowest 088 * integer is already set, then the new lowest integer overrides the 089 * previous one. 090 * 091 * @param intLow the lowest integer 092 * @return this builder 093 */ 094 public ScopeBuilder intLow(int intLow) { 095 this.intLow = intLow; 096 return this; 097 } 098 099 /** 100 * Adjust the lowest integer used for solving. 101 * 102 * @param adjust increment the lowest integer by this amount 103 * @return this builder 104 */ 105 public ScopeBuilder adjustIntLow(int adjust) { 106 intLow += adjust; 107 return this; 108 } 109 110 /** 111 * Set the highest (inclusive) integer used for solving. If the highest 112 * integer is already set, then the new highest integer overrides the 113 * previous one. 114 * 115 * @param intHigh the highest integer 116 * @return this builder 117 */ 118 public ScopeBuilder intHigh(int intHigh) { 119 this.intHigh = intHigh; 120 return this; 121 } 122 123 /** 124 * Adjust the highest integer used for solving. 125 * 126 * @param adjust increment the highest integer by this amount 127 * @return this builder 128 */ 129 public ScopeBuilder adjustIntHigh(int adjust) { 130 intHigh += adjust; 131 return this; 132 } 133 134 /** 135 * Finalizes all the decisions made in the builder. Further changes to this 136 * builder is permitted for building more scopes, but the returned scope 137 * will not be affected. 138 * 139 * @return the built scope 140 */ 141 @Override 142 public Scope toScope() { 143 return new Scope(scope, defaultScope, intLow, intHigh); 144 } 145}