    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}