001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.compress.harmony.unpack200.bytecode;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023import java.util.Objects;
024
025/**
026 * Field reference constant pool entry.
027 */
028public class CPFieldRef extends ConstantPoolEntry {
029
030    CPClass className;
031    transient int classNameIndex;
032    private final CPNameAndType nameAndType;
033    transient int nameAndTypeIndex;
034
035    private boolean hashCodeComputed;
036
037    private int cachedHashCode;
038
039    public CPFieldRef(final CPClass className, final CPNameAndType descriptor, final int globalIndex) {
040        super(CP_Fieldref, globalIndex);
041        this.className = className;
042        this.nameAndType = descriptor;
043    }
044
045    @Override
046    public boolean equals(final Object obj) {
047        if (this == obj) {
048            return true;
049        }
050        if (obj == null || getClass() != obj.getClass()) {
051            return false;
052        }
053        final CPFieldRef other = (CPFieldRef) obj;
054        return Objects.equals(className, other.className)
055                && Objects.equals(nameAndType, other.nameAndType);
056    }
057
058    private void generateHashCode() {
059        hashCodeComputed = true;
060        final int PRIME = 31;
061        int result = 1;
062        result = PRIME * result + (className == null ? 0 : className.hashCode());
063        result = PRIME * result + (nameAndType == null ? 0 : nameAndType.hashCode());
064        cachedHashCode = result;
065    }
066
067    @Override
068    protected ClassFileEntry[] getNestedClassFileEntries() {
069        return new ClassFileEntry[] { className, nameAndType };
070    }
071
072    @Override
073    public int hashCode() {
074        if (!hashCodeComputed) {
075            generateHashCode();
076        }
077        return cachedHashCode;
078    }
079
080    @Override
081    protected void resolve(final ClassConstantPool pool) {
082        super.resolve(pool);
083        nameAndTypeIndex = pool.indexOf(nameAndType);
084        classNameIndex = pool.indexOf(className);
085    }
086
087    @Override
088    public String toString() {
089        return "FieldRef: " + className + "#" + nameAndType;
090    }
091
092    @Override
093    protected void writeBody(final DataOutputStream dos) throws IOException {
094        dos.writeShort(classNameIndex);
095        dos.writeShort(nameAndTypeIndex);
096    }
097
098}