class QueryTypeNameKey {
    /** */
    private final String cacheName;

    /** */
    private final String typeName;

    /**
     * @param cacheName Cache name.
     * @param typeName Type name.
     */
    public QueryTypeNameKey(@Nullable String cacheName, String typeName) {
        assert !F.isEmpty(typeName) : typeName;

        this.cacheName = cacheName;
        this.typeName = typeName;
    }

    /** {@inheritDoc} */
    @Override public boolean equals(Object o) {<FILL_FUNCTION_BODY>}

    /** {@inheritDoc} */
    @Override public int hashCode() {
        return 31 * (cacheName != null ? cacheName.hashCode() : 0) + typeName.hashCode();
    }

    /** {@inheritDoc} */
    @Override public String toString() {
        return S.toString(QueryTypeNameKey.class, this);
    }
}

        if (this == o)
            return true;

        if (o == null || getClass() != o.getClass())
            return false;

        QueryTypeNameKey other = (QueryTypeNameKey)o;

        return (cacheName != null ? cacheName.equals(other.cacheName) : other.cacheName == null) &&
            typeName.equals(other.typeName);
    
<no_super_class>