001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.generic;
019
020/**
021 * BranchHandle is returned by specialized InstructionList.append() whenever a
022 * BranchInstruction is appended. This is useful when the target of this
023 * instruction is not known at time of creation and must be set later
024 * via setTarget().
025 *
026 * @see InstructionHandle
027 * @see Instruction
028 * @see InstructionList
029 * @version $Id$
030 */
031public final class BranchHandle extends InstructionHandle {
032
033    // This is also a cache in case the InstructionHandle#swapInstruction() method is used
034    // See BCEL-273
035    private BranchInstruction bi; // An alias in fact, but saves lots of casts
036
037
038    private BranchHandle(final BranchInstruction i) {
039        super(i);
040        bi = i;
041    }
042
043    /** Factory method.
044     */
045    static BranchHandle getBranchHandle( final BranchInstruction i ) {
046        return new BranchHandle(i);
047    }
048
049
050    /* Override InstructionHandle methods: delegate to branch instruction.
051     * Through this overriding all access to the private i_position field should
052     * be prevented.
053     */
054    @Override
055    public int getPosition() {
056        return bi.getPosition();
057    }
058
059
060    @Override
061    void setPosition( final int pos ) {
062        // Original code: i_position = bi.position = pos;
063        bi.setPosition(pos);
064        super.setPosition(pos);
065    }
066
067
068    @Override
069    protected int updatePosition( final int offset, final int max_offset ) {
070        final int x = bi.updatePosition(offset, max_offset);
071        super.setPosition(bi.getPosition());
072        return x;
073    }
074
075
076    /**
077     * Pass new target to instruction.
078     */
079    public void setTarget( final InstructionHandle ih ) {
080        bi.setTarget(ih);
081    }
082
083
084    /**
085     * Update target of instruction.
086     */
087    public void updateTarget( final InstructionHandle old_ih, final InstructionHandle new_ih ) {
088        bi.updateTarget(old_ih, new_ih);
089    }
090
091
092    /**
093     * @return target of instruction.
094     */
095    public InstructionHandle getTarget() {
096        return bi.getTarget();
097    }
098
099
100    /**
101     * Set new contents. Old instruction is disposed and may not be used anymore.
102     */
103    @Override // This is only done in order to apply the additional type check; could be merged with super impl.
104    public void setInstruction( final Instruction i ) { // TODO could be package-protected?
105        super.setInstruction(i);
106        if (!(i instanceof BranchInstruction)) {
107            throw new ClassGenException("Assigning " + i
108                    + " to branch handle which is not a branch instruction");
109        }
110        bi = (BranchInstruction) i;
111    }
112}