Description
A utility method throwing an error to indicate that a method used by a default implementation of another method has not been overridden.
License
Open Source License
Parameter
Parameter | Description |
---|
thisClassName | the name of the class |
thisMethodsName | the method name |
superClassName | the super class name |
namesOfMethodsWhoseDefaultImplementationUsesThisMethod | names of methods whose default implementation uses this method |
Exception
Parameter | Description |
---|
Error | if one occurs |
Declaration
public static void throwSafeguardError(String thisClassName, String thisMethodsName, String superClassName,
String... namesOfMethodsWhoseDefaultImplementationUsesThisMethod) throws Error
Method Source Code
//package com.java2s;
/*/* ww w.j a v a2 s.c o m*/
* Copyright (c) 2013, SRI International
* All rights reserved.
* Licensed under the The BSD 3-Clause License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://opensource.org/licenses/BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the aic-util nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
public class Main {
/**
* A utility method throwing an error to indicate that a method used by a default implementation of another method
* has not been overridden.
* <p>
* This is useful in the following situation.
* Suppose a class Vehicle (superClassName) provides a default implementation for checkUp() (nameOfMethodWhoseDefaultImplementationUsesThisMethod)
* that assumes the Vehicle has tires in the first place,
* and uses an abstract method tiresType() (thisMethodsName). Since a lot of vehicles do use tires, such default implementation is very convenient.
* However, we do not want to make life harder for people extending Vehicle to represent vehicles without tires (such as a class Boat (thisClassName)),
* and forcing them to implement tiresType() with some dummy code would be ugly and distracting.
* Besides, the developer may not notice that checkUp() assumes tires, and as a result may not override it (as they should since Boat violates that assumption).
* In that case, the dummy code in tiresType() code will be invoked even though it should not.
* <p>
* The solution is to change tiresType() from abstract to an implemented method simply invoking this Error-throwing safeguard utility.
* If the developer overrides checkUp(), as they should in the case of Boat, the fact that tiresType() is no longer an abstract method
* will prevent the compiler from insisting on its unnecessary implementation.
* If the developer does not override checkUp() (for example, while extending Vehicle to a class Car),
* but forgets to override tiresType() (since it is not abstract anymore, the compiler will not complain),
* then there will be an Error thrown at run-time by this utility safeguard method.
* <p>
* In other words, because tiresType() is "abstract" only as a result of using a default, optional implementation,
* we make it not technically abstract and required in compile-time, but still "abstract" in a run-time sense of
* an implementation being demanded in case it is actually needed.
*
* @param thisClassName
* the name of the class
* @param thisMethodsName
* the method name
* @param superClassName
* the super class name
* @param namesOfMethodsWhoseDefaultImplementationUsesThisMethod
* names of methods whose default implementation uses this method
* @throws Error if one occurs
*/
public static void throwSafeguardError(String thisClassName, String thisMethodsName, String superClassName,
String... namesOfMethodsWhoseDefaultImplementationUsesThisMethod) throws Error {
String oneOf = namesOfMethodsWhoseDefaultImplementationUsesThisMethod.length > 1 ? "one of " : "";
throw new Error(thisMethodsName + " is being invoked but has not been overridden by " + thisClassName + ". "
+ "It is probably being invoked by the default implementation of " + oneOf
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " in " + superClassName
+ ", unless some other overriding method invokes it. " + "If the default implementation of "
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " in " + superClassName
+ " is being used, " + thisMethodsName + " should be overridden," + " or if " + thisMethodsName
+ " does not make sense for " + thisClassName
+ " (because of some assumption made by the default implementation of "
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " that does not hold in "
+ thisClassName + "), then a new implementation of "
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " should override the default one;"
+ " if on the other hand the default implementation of "
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod)
+ " has been overridden, then its new version, or some other overriding method, is invoking "
+ thisMethodsName + ", which (typically) should not happen (because " + thisMethodsName
+ " conforms to the assumptions made by the default" + " implementation of "
+ join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod)
+ " and the overriding of the latter indicates that those assumptions probably do not hold anymore.");
}
/**
* Returns the string formed by concatenating the two given strings, with a
* space in between if both strings are non-empty.
*
* @param str1
* the first string to join.
* @param str2
* the second string to join.
* @return a concatenated version of str1 and str2 with a space in between.
*/
public static String join(String str1, String str2) {
if (str1.length() == 0) {
return str2;
}
if (str2.length() == 0) {
return str1;
}
StringJoiner sj = new StringJoiner(" ");
sj.add(str1).add(str2);
return sj.toString();
}
/**
* Returns a string formed by the concatenation of string versions of the
* elements in a collection, separated by a given separator.
*
* @param separator
* the separator to use between elements when creating the joined
* string.
* @param c
* the collection whose elements toString() values are to be
* joined together.
* @return a String constructed from the toString of each element of the
* given collection with the given separator between each argument.
*/
public static String join(String separator, Collection c) {
Iterator it = c.iterator();
return join(separator, it);
}
/**
* Returns a string formed by the concatenation of string versions of the
* elements in an iterator's range, separated by a given separator.
*
* @param separator
* the separator to use between elements when creating the joined
* string.
* @param it
* the iterator whose elements toString() values are to be joined
* together.
* @return a String constructed from the toString of each element of the
* given iterator with the given separator between each argument.
*/
@SuppressWarnings("unchecked")
public static String join(String separator, Iterator it) {
StringJoiner sj = new StringJoiner(separator);
it.forEachRemaining(e -> sj.add(e == null ? "null" : e.toString()));
return sj.toString();
}
/**
* Same as {@link #join(String, Iterator)}, with <code>", "</code> for a
* separator.
*
* @param it
* the iterator whose elements toString() values are to be joined
* together.
* @return a String constructed from the toString of each element of the
* given iterator with a comma (<code>", "</code>) separator between
* each argument.
*/
public static String join(Iterator it) {
return join(", ", it);
}
/**
* Same as {@link #join(String, Collection)}.
*
* @param c
* the collection whose elements toString() values are to be
* joined together.
* @param separator
* the separator to use between elements when creating the joined
* string.
* @return a String constructed from the toString of each element of the
* given collection with the given separator between each argument.
*/
public static String join(Collection c, String separator) {
return join(separator, c);
}
/**
* Calls {@link #join(String, Collection)} with ", " as separator.
*
* @param c
* the collection whose elements toString() values are to be
* joined together.
* @return a String constructed from the toString of each element of the
* given collection with a comma (<code>", "</code>) separator
* between each argument.
*/
public static String join(Collection c) {
return join(", ", c);
}
/**
* Calls {@link #join(Collection)} on the given array as a collection.
*
* @param a
* the array whose elements toString() values are to be joined
* together.
* @return a String constructed from the toString of each element of the
* given array with a comma (<code>", "</code>) separator between
* each argument.
*/
public static String join(Object[] a) {
return join(Arrays.asList(a));
}
/**
* Calls {@link #join(String, Collection)} on the given array as a
* collection.
*
* @param separator
* the separator to use between elements when creating the joined
* string.
* @param a
* the array whose elements toString() values are to be joined
* together.
* @return a String constructed from the toString of each element of the
* given array with the given separator between each argument.
*/
public static String join(String separator, Object[] a) {
return join(separator, Arrays.asList(a));
}
/**
* Produces a string with map entry representations separated by a given
* entry separator, where entry representations are the key and value
* representations separated by a key-value separator.
*
* @param entrySeparator
* the separator to use between each map entry in the join
* output.
* @param keyValueSeparator
* the separator to use between each entry's key value pair in
* the join output.
* @param map
* the map whose key value pairs are to be joined into a String.
* @return a joined string with an entrySeparator between each entry in the
* given map, each of which has a keyValueSeparator between the
* entry's key and value.
*/
public static String join(String entrySeparator, String keyValueSeparator,
Map<? extends Object, ? extends Object> map) {
List<Object> c = new LinkedList<Object>();
for (Map.Entry<? extends Object, ? extends Object> entry : map.entrySet()) {
c.add(entry.getKey() + keyValueSeparator + entry.getValue());
}
return join(entrySeparator, c);
}
/**
* Same as {@link #join(String, String, Map)} with key-value separator equal
* to -> .
*
* @param entrySeparator
* the separator to use between each map entry in the join
* output.
* @param map
* the map whose key value pairs are to be joined into a String.
* @return a joined string with an entrySeparator between each entry in the
* given map, each of which has an arrow -> separator between the
* entry's key and value.
*/
public static String join(String entrySeparator, Map<? extends Object, ? extends Object> map) {
return join(entrySeparator, " -> ", map);
}
/**
* Same as {@link #join(String, String, Map)} with entry separator equal to
* <code>", "</code> and key-value separator equal to ->.
*
* @param map
* the map whose key value pairs are to be joined into a String.
* @return a joined string with a <code>", "</code> comma separator between
* each entry in the given map, each of which has an arrow ->
* separator between the entry's key and value.
*/
public static String join(Map<? extends Object, ? extends Object> map) {
return join(", ", " -> ", map);
}
/**
* Construct an iterator of the given type ranging over provided elements.
*
* @param elements
* the elements to construct the List from.
* @return an iterator over the received arguments.
* @param <T>
* the type of elements the iterator will range over.
*/
public static <T> Iterator<T> iterator(T... elements) {
return Arrays.asList(elements).iterator();
}
}
Related
- joinRepeating(String element, String delimiter, int times)
- joinToString(String sep, Iterable items)
- listToString(List list)
- print(int[] a)
- split(String s)
- toCVS(Set buildRecordSetIds)