All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.electronwill.nightconfig.core.AbstractCommentedConfig Maven / Gradle / Ivy

package com.electronwill.nightconfig.core;

import com.electronwill.nightconfig.core.utils.TransformingSet;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * An abstract CommentedConfig backed by two maps: one for the values and one for the comments.
 * The comments of the subconfigs are stored in these subconfigs.
 *
 * @author TheElectronWill
 */
public abstract class AbstractCommentedConfig extends AbstractConfig implements CommentedConfig {
	private final Map commentMap;

	public AbstractCommentedConfig(boolean concurrent) {
		super(concurrent);
		this.commentMap = concurrent ? new ConcurrentHashMap<>() : new HashMap<>();
	}

	/**
	 * Creates an AbstractCommentedConfig backed by the specified map
	 *
	 * @param valuesMap the map containing the config's values
	 */
	public AbstractCommentedConfig(Map valuesMap) {
		super(valuesMap);
		this.commentMap = new HashMap<>();
	}

	/**
	 * Creates an AbstractCommentedConfig that is a copy of the specified config.
	 *
	 * @param toCopy the config to copy
	 */
	public AbstractCommentedConfig(UnmodifiableConfig toCopy, boolean concurrent) {
		super(toCopy, concurrent);
		this.commentMap = concurrent ? new ConcurrentHashMap<>() : new HashMap<>();
	}

	/**
	 * Creates an AbstractCommentedConfig that is a copy of the specified config.
	 *
	 * @param toCopy the config to copy
	 */
	public AbstractCommentedConfig(UnmodifiableCommentedConfig toCopy, boolean concurrent) {
		super(toCopy.valueMap());
		this.commentMap = new HashMap<>(toCopy.commentMap());
	}

	@Override
	public String getComment(List path) {
		final int lastIndex = path.size() - 1;
		final String lastKey = path.get(lastIndex);
		if (lastIndex == 0) {
			return commentMap.get(lastKey);
		}
		Object parent = getRaw(path.subList(0, lastIndex));
		if (parent instanceof UnmodifiableCommentedConfig) {
			List lastPath = Collections.singletonList(lastKey);
			return ((UnmodifiableCommentedConfig)parent).getComment(lastPath);
		}
		return null;
	}

	@Override
	public String setComment(List path, String comment) {
		final int lastIndex = path.size() - 1;
		final String lastKey = path.get(lastIndex);
		if (lastIndex == 0) {
			return commentMap.put(lastKey, comment);
		}
		final List parentPath = path.subList(0, lastIndex);
		Object parent = getRaw(parentPath);
		List lastPath = Collections.singletonList(lastKey);
		if (parent instanceof CommentedConfig) {
			return ((CommentedConfig)parent).setComment(lastPath, comment);
		} else if (parent == null) {
			CommentedConfig commentedParent = createSubConfig();
			set(parentPath, commentedParent);
			return commentedParent.setComment(lastPath, comment);
		}
		throw new IllegalArgumentException("Cannot set a comment to path "
										   + path
										   + " because the parent entry is of incompatible type "
										   + parent.getClass());
	}

	@Override
	public String removeComment(List path) {
		final int lastIndex = path.size() - 1;
		final String lastKey = path.get(lastIndex);
		if (lastIndex == 0) {
			return commentMap.remove(lastKey);
		}
		Object parent = getRaw(path.subList(0, lastIndex));
		if (parent instanceof CommentedConfig) {
			List lastPath = Collections.singletonList(lastKey);
			return ((CommentedConfig)parent).removeComment(lastPath);
		}
		return null;
	}

	@Override
	public boolean containsComment(List path) {
		final int lastIndex = path.size() - 1;
		final String lastKey = path.get(lastIndex);
		if (lastIndex == 0) {
			return commentMap.containsKey(lastKey);
		}
		Object parent = getRaw(path.subList(0, lastIndex));
		if (parent instanceof CommentedConfig) {
			List lastPath = Collections.singletonList(lastKey);
			return ((CommentedConfig)parent).containsComment(lastPath);
		}
		return false;
	}

	@Override
	public Map commentMap() {
		return commentMap;
	}

	@Override
	public Set entrySet() {
		return new TransformingSet<>(map.entrySet(), CommentedEntryWrapper::new, o -> null, o -> o);
	}

	/**
	 * @return a new config that contains the same entries (including comments) as this config.
	 */
	@Override
	public abstract AbstractCommentedConfig clone();

	protected class CommentedEntryWrapper extends EntryWrapper implements CommentedConfig.Entry {
		private List path = null;

		public CommentedEntryWrapper(Map.Entry mapEntry) {
			super(mapEntry);
		}

		protected List getPath() {
			if (path == null) {
				path = Collections.singletonList(getKey());
			}
			return path;
		}

		@Override
		public String getComment() {
			return AbstractCommentedConfig.this.getComment(getPath());
		}

		@Override
		public String setComment(String comment) {
			return AbstractCommentedConfig.this.setComment(getPath(), comment);
		}

		@Override
		public String removeComment() {
			return AbstractCommentedConfig.this.removeComment(getPath());
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == this) {
				return true;
			}
			if (obj instanceof CommentedEntryWrapper) {
				CommentedEntryWrapper other = (CommentedEntryWrapper)obj;
				return Objects.equals(getKey(), other.getKey())
					   && Objects.equals(getValue(), other.getValue())
					   && Objects.equals(getComment(), other.getComment());
			}
			return false;
		}

		@Override
		public int hashCode() {
			int result = 1;
			result = 31 * result + Objects.hashCode(getKey());
			result = 31 * result + Objects.hashCode(getValue());
			result = 31 * result + Objects.hashCode(getComment());
			return result;
		}
	}

	@Override
	public void clear() {
		super.clear();
		clearComments();
	}

	@Override
	public void clearComments() {
		commentMap.clear();
		// Recursively clears the comments of the subconfigs:
		for (Object o : map.values()) {
			if (o instanceof CommentedConfig) {
				((CommentedConfig)o).clearComments();
			}
		}
		//NB: The UnmodifiableCommentedConfigs cannot be cleared from their comments.
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy