Skip to content

Commit

Permalink
improved meta-info
Browse files Browse the repository at this point in the history
  • Loading branch information
hohwille committed Dec 13, 2023
1 parent e31ab06 commit 002b11f
Show file tree
Hide file tree
Showing 17 changed files with 527 additions and 309 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.github.mmm.base.collection;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
* Abstract base implementation of {@link Iterator} as reusable pattern to simplify implementations of {@link Iterator}.
* Please carefully consider the following constraints before use:
* <ul>
* <li>This {@link Iterator} cannot iterate {@code null} elements.</li>
* <li>Implementations extending {@link AbstractIterator} have to call {@link #findFirst()} at the end of their
* constructor.</li>
* <li>Finally, you only to do implement {@link #findNext()}.</li>
* </ul>
*
* @param <E> type of the elements to {@link #next() iterate}.
*/
public abstract class AbstractIterator<E> implements Iterator<E> {

/** @see #next() */
private E next;

/**
* Has to be called from the constructor after initialization of fields to find the first element.
*/
protected final void findFirst() {

this.next = findNext();
}

/**
* @return the next element or {@code null} if done.
*/
protected abstract E findNext();

@Override
public final boolean hasNext() {

return this.next != null;
}

@Override
public final E next() {

if (this.next == null) {
throw new NoSuchElementException();
} else {
E result = this.next;
this.next = findNext();
return result;
}
}

@Override
public String toString() {

return "Iterator at " + this.next;
}

}
29 changes: 22 additions & 7 deletions metainfo/src/main/java/io/github/mmm/base/metainfo/MetaInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ default boolean getAsBoolean(boolean inherit, String key, boolean defaultValue)
*/
default boolean isEmpty() {

return size() == 0;
return !iterator().hasNext();
}

/**
Expand All @@ -210,6 +210,17 @@ default MetaInfo getParent() {
return null;
}

/**
* @return the prefix for the {@link #get(String) keys} as namespace. E.g. if the key prefix is "spring.datasource."
* and you call {@link #get(String)} with "password" it will return the property for the key
* "spring.datasource.password" from the underlying mapping. The default key prefix is the empty
* {@link String}.
*/
default String getKeyPrefix() {

return "";
}

/**
* Adds or updates the specified meta-info.<br>
* <b>ATTENTION:</b> Please consider using {@link #with(Map)} and other related factory methods instead of
Expand All @@ -233,9 +244,7 @@ default MetaInfo with(Map<String, String> map) {

/**
* @param map the {@link Map} with the meta-information to wrap.
* @param keyPrefix the prefix for the {@link #get(String) keys} as namespace. E.g. when using "spring.datasource."
* and you call {@link #get(String)} with "password" it will return the property for the key
* "spring.datasource.password" from the given {@link Properties}.
* @param keyPrefix the {@link #getKeyPrefix() key prefix}.
* @return a new {@link MetaInfo} that extends this {@link MetaInfo} with the specified meta-information.
*/
MetaInfo with(Map<String, String> map, String keyPrefix);
Expand All @@ -257,9 +266,7 @@ default MetaInfo with(Properties properties) {
* the parent defaults) the result will be inefficient.
*
* @param properties the {@link Properties} with the meta-information to wrap.
* @param keyPrefix the prefix for the {@link #get(String) keys} as namespace. E.g. when using "spring.datasource."
* and you call {@link #get(String)} with "password" it will return the property for the key
* "spring.datasource.password" from the given {@link Properties}.
* @param keyPrefix the {@link #getKeyPrefix() key prefix}.
* @return a new {@link MetaInfo} that extends this {@link MetaInfo} with the specified meta-information.
*/
MetaInfo with(Properties properties, String keyPrefix);
Expand Down Expand Up @@ -287,6 +294,14 @@ default MetaInfo with(AnnotatedElement annotatedElement) {
*/
MetaInfo with(MetaInfos metaValues);

/**
* @param keyPrefix the {@link #getKeyPrefix() key prefix}.
* @return a new {@link MetaInfo} that wraps this {@link MetaInfo} with all its parents using the given
* {@link #getKeyPrefix() key prefix}. The resulting {@link MetaInfo} will return {@code null} as
* {@link #getParent() parent}.
*/
MetaInfo with(String keyPrefix);

/**
* @return an instance of {@link MetaInfo} that is {@link #isEmpty() empty}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,91 @@ public AbstractMetaInfo getParent() {
}

/**
* @return {@code this} instance as {@link InheritedMetaInfo} to be used as {@link #getParent() parent} of a new child
* @return {@code this} instance as {@link MetaInfoInherited} to be used as {@link #getParent() parent} of a new child
* (see {@code with} methods) or {@code null} if this is the empty instance.
*/
protected InheritedMetaInfo asParent() {
protected MetaInfoInherited asParent() {

return null;
}

/**
* @param inherit the inherit flag from {@link #get(boolean, String)}. Typically to be ignored but may be used in
* special cases.
* @param key the key of the requested meta-information.
* @return the value of the meta-information for the given {@code key} without inheritance from {@link #getParent()
* parent}. Will be {@code null} if no value is defined for the given {@code key}.
* @see #get(boolean, String)
*/
protected abstract String getPlain(String key);
protected abstract String getPlain(boolean inherit, String key);

@Override
public String get(boolean inherit, String key) {

String value = getPlain(getKey(key));
return get(inherit, key, null);
}

/**
* @param inherit - {@code true} to inherit meta-information from the {@link #getParent() parent}, {@code false} to
* only return plain meta-information defined in this {@link MetaInfo} itself.
* @param key the key of the requested meta-information.
* @param stop the ancestor {@link AbstractMetaInfo} where to stop inheriting.
* @return the value of the meta-information for the given {@code key}. Will be {@code null} if no value is defined
* for the given {@code key}.
*/
public String get(boolean inherit, String key, MetaInfo stop) {

String value = getPlain(inherit, qualifyKey(key));

if ((value == null) && inherit) {
AbstractMetaInfo parent = getParent();
if (parent != null) {
if ((parent != null) && (parent != stop)) {
value = parent.get(true, key);
}
}
return value;
}

/**
* @return the prefix for the {@link #get(String) keys} as namespace. E.g. when using "spring.datasource." and you
* call {@link #get(String)} with "password" it will return the property for the key
* "spring.datasource.password" from the given {@link Properties}. The default value is the empty
* {@link String}.
* @param key the raw key.
* @return the qualified key with the {@link #getKeyPrefix() key prefix} prepended.
*/
public String getKeyPrefix() {
protected String qualifyKey(String key) {

return null;
String keyPrefix = getKeyPrefix();
if (keyPrefix.isEmpty() || (key == null)) {
return key;
}
return keyPrefix + key;
}

/**
* @param key the raw key.
* @return the qualified key with the {@link #getKeyPrefix() key prefix}.
* @return the unqualified key with the {@link #getKeyPrefix() key prefix} removed. Will be {@code null} if the key
* was {@code null} or the key did not {@link String#startsWith(String) start with} the {@link #getKeyPrefix()
* key prefix}.
*/
protected String getKey(String key) {
protected String unqualifyKey(String key) {

return key;
String keyPrefix = getKeyPrefix();
if (keyPrefix.isEmpty()) {
return key;
}
if ((key != null) && key.startsWith(keyPrefix)) {
return key.substring(keyPrefix.length());
}
return null;
}

@Override
public int size() {

int size = 0;
for (String key : this) {
assert (key != null);
size++;
}
return size;
}

@Override
Expand Down

This file was deleted.

Loading

0 comments on commit 002b11f

Please sign in to comment.