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 */
017package org.apache.juneau.commons.bean;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021
022import org.apache.juneau.commons.collections.*;
023
024/**
025 * Represents a simple bean property value and the meta-data associated with it.
026 *
027 * <h5 class='topic'>Thread safety</h5>
028 *
029 * Instances are immutable and thread-safe.
030 */
031@SuppressWarnings({
032   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
033   "java:S1452" // Wildcard required - Class<?> for property type metadata
034})
035public class BeanPropertyValue implements Comparable<BeanPropertyValue> {
036
037   private final BeanPropertyMeta pMeta;
038   private final String name;
039   private final Object value;
040   private final Throwable thrown;
041
042   /**
043    * Constructor.
044    *
045    * @param pMeta The bean property metadata.
046    * @param name The bean property name.
047    * @param value The bean property value.  Can be <jk>null</jk>.
048    * @param thrown The exception thrown by calling the property getter.  Can be <jk>null</jk> if no exception was thrown.
049    */
050   public BeanPropertyValue(BeanPropertyMeta pMeta, String name, Object value, Throwable thrown) {
051      this.pMeta = pMeta;
052      this.name = name;
053      this.value = value;
054      this.thrown = thrown;
055   }
056
057   @Override /* Overridden from Comparable */
058   public int compareTo(BeanPropertyValue o) {
059      return name.compareTo(o.name);
060   }
061
062   @Override /* Overridden from Object */
063   public boolean equals(Object o) {
064      return o instanceof BeanPropertyValue o2 && compareTo(o2) == 0;
065   }
066
067   @Override /* Overridden from Object */
068   public int hashCode() {
069      return name != null ? name.hashCode() : 0;
070   }
071
072   /**
073    * Returns the {@link BeanInfo} of the bean property.
074    *
075    * <p>
076    * Returns the bean-modeling-side SPI type ({@link BeanInfo}).  Marshalling-side callers that need the
077    * {@code ClassMeta} narrowing must cast — the concrete instance in-tree is always a
078    * {@code ClassMeta}.
079    *
080    * @return The bean property type info.
081    */
082   public final BeanInfo<?> getBeanInfo() { return pMeta.getBeanInfo(); }
083
084   /**
085    * Returns the bean property metadata.
086    *
087    * @return The bean property metadata.
088    */
089   public final BeanPropertyMeta getMeta() { return pMeta; }
090
091   /**
092    * Returns the bean property name.
093    *
094    * @return The bean property name.
095    */
096   public final String getName() { return name; }
097
098   /**
099    * Returns the exception thrown by calling the property getter.
100    *
101    * @return The exception thrown by calling the property getter.
102    */
103   public final Throwable getThrown() { return thrown; }
104
105   /**
106    * Returns the bean property value.
107    *
108    * @return The bean property value.
109    */
110   public final Object getValue() { return value; }
111
112   /**
113    * Returns a property map view of this object.
114    *
115    * @return A property map containing the name, value, and type of this bean property.
116    */
117   public FluentMap<String,Object> properties() {
118      // @formatter:off
119      return filteredBeanPropertyMap()
120         .a("name", name)
121         .a("value", value)
122         .a("type", cns(pMeta.getBeanInfo()));
123      // @formatter:on
124   }
125
126   @Override /* Overridden from Object */
127   public String toString() {
128      return r(properties());
129   }
130}