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.rest.server.httppart;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021
022import java.util.*;
023import java.util.function.*;
024
025import org.apache.juneau.marshall.*;
026import org.apache.juneau.bct.assertions.*;
027
028/**
029 * Implementation of a named object.
030 *
031 * <h5 class='section'>See Also:</h5><ul>
032 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerHttpParts">HTTP parts in REST servers</a>
033 * </ul>
034 */
035@Marshalled(as=MarshalledAs.STRING)
036public class BasicNamedAttribute implements NamedAttribute {
037
038   /**
039    * Static creator.
040    *
041    * @param name The parameter name.
042    * @param value The parameter value.
043    * @return A new {@link BasicNamedAttribute} object.
044    */
045   public static BasicNamedAttribute of(String name, Object value) {
046      return new BasicNamedAttribute(name, value);
047   }
048
049   /**
050    * Static creator with delayed value.
051    *
052    * <p>
053    * Value is re-evaluated on each call to {@link #getValue()}.
054    *
055    * @param name The parameter name.
056    * @param value The parameter value supplier.
057    * @return A new {@link BasicNamedAttribute} object.
058    */
059   public static BasicNamedAttribute of(String name, Supplier<?> value) {
060      return new BasicNamedAttribute(name, value);
061   }
062
063   /**
064    * Creates a {@link BasicNamedAttribute} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
065    *
066    * @param pair The pair string.  Can be <jk>null</jk>, in which case <jk>null</jk> is returned.
067    * @return A new {@link BasicNamedAttribute} object, or <jk>null</jk> if the pair string was <jk>null</jk>.
068    */
069   public static BasicNamedAttribute ofPair(String pair) {
070      if (pair == null)
071         return null;
072      var i = pair.indexOf(':');
073      if (i == -1)
074         i = pair.indexOf('=');
075      if (i == -1)
076         return of(pair, "");
077      return of(pair.substring(0, i).trim(), pair.substring(i + 1).trim());
078   }
079
080   private final String name;
081   private final Object value;
082
083   /**
084    * Constructor.
085    *
086    * @param name The parameter name.
087    * @param value The POJO to serialize to the parameter value.
088    */
089   public BasicNamedAttribute(String name, Object value) {
090      this.name = name;
091      this.value = value;
092   }
093
094   /**
095    * Copy constructor.
096    *
097    * @param copyOf The object to copy.
098    */
099   protected BasicNamedAttribute(BasicNamedAttribute copyOf) {
100      this.name = copyOf.name;
101      this.value = copyOf.value;
102   }
103
104   /**
105    * Provides an object for performing assertions against the name of this pair.
106    *
107    * @return An object for performing assertions against the name of this pair.
108    */
109   public FluentStringAssertion<BasicNamedAttribute> assertName() {
110      return new FluentStringAssertion<>(getName(), this);
111   }
112
113   /**
114    * Provides an object for performing assertions against the value of this pair.
115    *
116    * @return An object for performing assertions against the value of this pair.
117    */
118   public FluentObjectAssertion<Object,BasicNamedAttribute> assertValue() {
119      return new FluentObjectAssertion<>(getValue(), this);
120   }
121
122   /**
123    * If a value is present, returns the value, otherwise throws {@link NoSuchElementException}.
124    *
125    * <p>
126    * This is a shortcut for calling <c>asString().get()</c>.
127    *
128    * @return The value if present.
129    */
130   public Object get() {
131      Object o = getValue();
132      if (o == null)
133         throw new NoSuchElementException();
134      return o;
135   }
136
137   @Override /* Overridden from NamedAttribute */
138   public String getName() { return name; }
139
140   @Override /* Overridden from NamedAttribute */
141   public Object getValue() { return unwrap(value); }
142
143   /**
144    * Returns <jk>true</jk> if the value exists.
145    *
146    * <p>
147    * This is a shortcut for calling <c>asString().isPresent()</c>.
148    *
149    * @return <jk>true</jk> if the value exists.
150    */
151   public boolean isPresent() { return nn(getValue()); }
152
153   /**
154    * If a value is present, returns the value, otherwise returns other.
155    *
156    * <p>
157    * This is a shortcut for calling <c>asString().orElse(<jv>other</jv>)</c>.
158    *
159    * @param other The other value.
160    * @return The value if present or the other value if not.
161    */
162   public Object orElse(Object other) {
163      Object o = getValue();
164      return nn(o) ? o : other;
165   }
166
167   @Override /* Overridden from Object */
168   public String toString() {
169      return urlEncode(getName()) + "=" + getValue();
170   }
171
172   private static Object unwrap(Object o) {
173      while (o instanceof Supplier)
174         o = ((Supplier<?>)o).get();
175      return o;
176   }
177}