/** * Adds a map context to the chain. This means that the transformation associated to the passed * context will be applied after all the currently queued transformations. An exception will be * thrown if the chain already contains an object of the same class as <code>mapCtx</code>. This * is because we don't want to compose the same transformation twice. This method adds a copy of * <code>mapCtx</code> to the chain. This is because we want to exclude the possibility that the * context's state can be modified after the lookup table is built. This method triggers a * re-build of the lookup table. * * @param mapCtx The context to add. Mustn't be <code>null</code>. * @throws IllegalArgumentException If the context is already defined. */ public void add(CodomainMapContext mapCtx) { if (mapCtx == null) { throw new NullPointerException("No context."); } if (chain.contains(mapCtx)) { throw new IllegalArgumentException("Context already defined."); } mapCtx = mapCtx.copy(); // Get memento and discard original object. mapCtx.setCodomain(intervalStart, intervalEnd); mapCtx.buildContext(); chain.add(mapCtx); buildLUT(); }
/** * Sets the codomain interval. This triggers an update of all map contexts in the chain and a * re-build of the lookup table. The interval defined by <code>start</code> and <code>end</code> * must be a sub-interval of <code>[{@link QuantumStrategy#MIN}, {@link QuantumStrategy#MAX}] * </code>. * * @param start The lower bound of the codomain interval. * @param end The upper bound of the codomain interval. */ public void setInterval(int start, int end) { verifyInterval(start, end); intervalStart = start; intervalEnd = end; CodomainMapContext ctx; Iterator i = chain.iterator(); while (i.hasNext()) { ctx = (CodomainMapContext) i.next(); ctx.setCodomain(start, end); ctx.buildContext(); } buildLUT(); }
/** * Updates a map context in the chain. An exception will be thrown if the chain doesn't contain an * object of the same class as <code>mapCtx</code>. This method replaces the old context with a * copy of <code>mapCtx</code>. This is because we want to exclude the possibility that the * context's state can be modified after the lookup table is built. This method triggers a * re-build of the lookup table. * * @param mapCtx The context to add. Mustn't be <code>null</code> and already contained in the * chain. * @throws IllegalArgumentException If the specifed context doesn't exist. */ public void update(CodomainMapContext mapCtx) { if (mapCtx == null) { throw new NullPointerException("No context."); } int i = chain.indexOf(mapCtx); // Recall equals() is overridden. if (i == -1) { throw new IllegalArgumentException("No such a context."); } mapCtx = mapCtx.copy(); // Get memento and discard original object. mapCtx.setCodomain(intervalStart, intervalEnd); mapCtx.buildContext(); chain.set(i, mapCtx); buildLUT(); }
/** Builds the lookup table. */ private void buildLUT() { LUT = new int[intervalEnd - intervalStart + 1]; CodomainMap map; CodomainMapContext ctx; int v; Iterator i; for (int x = intervalStart; x <= intervalEnd; ++x) { v = x; i = chain.iterator(); while (i.hasNext()) { ctx = (CodomainMapContext) i.next(); map = ctx.getCodomainMap(); map.setContext(ctx); v = map.transform(v); } LUT[x - intervalStart] = v; } }
/** * Overrides the toString method. * * @see Object#toString() */ @Override public String toString() { StringBuffer buf = new StringBuffer(); Iterator i = chain.iterator(); CodomainMapContext mapCtx; int n = chain.size(); int j = 1; while (i.hasNext()) { mapCtx = (CodomainMapContext) i.next(); buf.append(mapCtx.getCodomainMap()); if (j == n) { buf.append("."); } else { buf.append(", "); } j++; } return buf.toString(); }
/** * Creates a new chain. The chain will contain the specified contexts — if <code>mapContexts * </code> is <code>null</code> or empty, the chain will contain only the identity context. The * interval defined by <code>start</code> and <code>end</code> has to be a sub-interval of <code> * [{@link QuantumStrategy#MIN}, {@link QuantumStrategy#MAX}]</code>. * * @param start The lower bound of the codomain interval. * @param end The upper bound of the codomain interval. * @param mapContexts The sequence of {@link CodomainMapContext} objects that define the chain. No * two objects of the same class are allowed. The objects in this list are copied. * @throws IllegalArgumentException If one of the contexts is already defined. */ public CodomainChain(int start, int end, List mapContexts) { chain = new ArrayList(); if (identityCtx == null) { identityCtx = new IdentityMapContext(); } if (mapContexts != null && 0 < mapContexts.size()) { Iterator i = mapContexts.iterator(); CodomainMapContext ctx; while (i.hasNext()) { ctx = (CodomainMapContext) i.next(); if (chain.contains(ctx)) { throw new IllegalArgumentException("Context already defined."); } ctx = ctx.copy(); chain.add(ctx); } } else { chain.add(identityCtx); } setInterval(start, end); }