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

com.navercorp.fixturemonkey.expression.ArbitraryExpression Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
/*
 * Fixture Monkey
 *
 * Copyright (c) 2021-present NAVER Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.navercorp.fixturemonkey.expression;

import static com.navercorp.fixturemonkey.Constants.ALL_INDEX_STRING;
import static com.navercorp.fixturemonkey.Constants.HEAD_NAME;
import static com.navercorp.fixturemonkey.Constants.NO_OR_ALL_INDEX_INTEGER_VALUE;
import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

import com.navercorp.fixturemonkey.tree.CompositeNodeResolver;
import com.navercorp.fixturemonkey.tree.ContainerElementPredicate;
import com.navercorp.fixturemonkey.tree.DefaultNodeResolver;
import com.navercorp.fixturemonkey.tree.IdentityNodeResolver;
import com.navercorp.fixturemonkey.tree.NodeResolver;
import com.navercorp.fixturemonkey.tree.PropertyNameNodePredicate;

public final class ArbitraryExpression implements MonkeyExpression, Comparable {
	private final List expList;

	private ArbitraryExpression(List expList) {
		this.expList = expList;
	}

	private ArbitraryExpression(String expression) {
		expList = Arrays.stream(expression.split("\\."))
			.map(Exp::new)
			.collect(toList());
	}

	public static ArbitraryExpression from(String expression) {
		return new ArbitraryExpression(expression);
	}

	public ArbitraryExpression addFirst(String expression) {
		String newStringExpression = expression + "." + this;
		return new ArbitraryExpression(newStringExpression);
	}

	public ArbitraryExpression addLast(String expression) {
		String newStringExpression = this + "." + expression;
		return new ArbitraryExpression(newStringExpression);
	}

	@API(since = "0.4.0", status = Status.MAINTAINED)
	public ArbitraryExpression pollLast() {
		if (expList.isEmpty()) {
			return this;
		}

		List newExpList = new ArrayList<>(this.expList);
		int lastIndex = newExpList.size() - 1;
		Exp lastExp = newExpList.get(lastIndex);
		newExpList.remove(lastIndex);

		if (!lastExp.indices.isEmpty()) {
			List newExpIndexList = new ArrayList<>(lastExp.indices);
			newExpIndexList.remove(newExpIndexList.size() - 1);
			lastExp = new Exp(lastExp.name, newExpIndexList);
			newExpList.add(lastExp);
		}
		return new ArbitraryExpression(newExpList);
	}

	@Override
	public int compareTo(ArbitraryExpression arbitraryExpression) {
		List oExpList = arbitraryExpression.expList;

		if (expList.size() != oExpList.size()) {
			return Integer.compare(expList.size(), oExpList.size());
		}

		for (int i = 0; i < expList.size(); i++) {
			Exp exp = expList.get(i);
			Exp oExp = oExpList.get(i);
			int expCompare = exp.compareTo(oExp);
			if (expCompare != 0) {
				return expCompare;
			}
		}

		return 0;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || getClass() != obj.getClass()) {
			return false;
		}
		ArbitraryExpression other = (ArbitraryExpression)obj;
		return expList.equals(other.expList);
	}

	@Override
	public int hashCode() {
		return Objects.hash(this.expList);
	}

	public String toString() {
		return expList.stream()
			.map(Exp::toString)
			.collect(Collectors.joining("."));
	}

	public NodeResolver toNodeResolver() {
		NodeResolver nodeResolver = null;

		for (Exp exp : expList) {
			if (nodeResolver == null) {
				nodeResolver = exp.toNodeResolver();
			} else {
				nodeResolver = new CompositeNodeResolver(nodeResolver, exp.toNodeResolver());
			}
		}
		return nodeResolver;
	}

	private static final class ExpIndex implements Comparable {
		public static final ExpIndex ALL_INDEX_EXP_INDEX = new ExpIndex(NO_OR_ALL_INDEX_INTEGER_VALUE);

		private final int index;

		public ExpIndex(int index) {
			this.index = index;
		}

		public int getIndex() {
			return index;
		}

		public boolean equalsIgnoreAllIndex(ExpIndex expIndex) {
			return this.index == expIndex.index;
		}

		@Override
		public int compareTo(ExpIndex expIndex) {
			return Integer.compare(this.index, expIndex.index);
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj) {
				return true;
			}
			if (obj == null || getClass() != obj.getClass()) {
				return false;
			}
			ExpIndex expIndex = (ExpIndex)obj;
			return index == expIndex.index || index == NO_OR_ALL_INDEX_INTEGER_VALUE
				|| expIndex.index == NO_OR_ALL_INDEX_INTEGER_VALUE;
		}

		@Override
		public int hashCode() {
			return 0; // for allIndex, hash always return 0.
		}

		public String toString() {
			return index == NO_OR_ALL_INDEX_INTEGER_VALUE ? ALL_INDEX_STRING : String.valueOf(index);
		}
	}

	private static final class Exp implements Comparable {
		private final String name;
		private final List indices;

		private Exp(String name, List indices) {
			this.name = name;
			this.indices = indices;
		}

		public Exp(String expression) {
			indices = new ArrayList<>();
			int li = expression.indexOf('[');
			int ri = expression.indexOf(']');

			if ((li != -1 && ri == -1) || (li == -1 && ri != -1)) {
				throw new IllegalArgumentException("expression is invalid. expression : " + expression);
			}

			if (li == -1) {
				this.name = expression;
			} else {
				this.name = expression.substring(0, li);
				while (li != -1 && ri != -1) {
					if (ri - li > 1) {
						String indexString = expression.substring(li + 1, ri);
						final int indexValue = indexString.equals(ALL_INDEX_STRING)
							? NO_OR_ALL_INDEX_INTEGER_VALUE
							: Integer.parseInt(indexString);
						this.indices.add(new ExpIndex(indexValue));
					}
					expression = expression.substring(ri + 1);
					li = expression.indexOf('[');
					ri = expression.indexOf(']');
				}
			}
		}

		public NodeResolver toNodeResolver() {
			NodeResolver nodeResolver = IdentityNodeResolver.INSTANCE;

			if (!HEAD_NAME.equals(name)) {
				nodeResolver = new CompositeNodeResolver(
					nodeResolver,
					new DefaultNodeResolver(new PropertyNameNodePredicate(name))
				);
			}

			for (ExpIndex index : indices) {
				nodeResolver = new CompositeNodeResolver(
					nodeResolver,
					new DefaultNodeResolver(new ContainerElementPredicate(index.getIndex()))
				);
			}
			return nodeResolver;
		}

		public String getName() {
			return name;
		}

		public List getIndices() {
			return indices;
		}

		public String toString() {
			String indexBrackets = indices.stream()
				.map(i -> "[" + i.toString() + "]")
				.collect(Collectors.joining());
			return name + indexBrackets;
		}

		@Override
		public int compareTo(Exp exp) {
			List indices = this.getIndices();
			List oIndices = exp.getIndices();

			if (exp.name.equals(this.name)) {
				int indexLength = Math.min(oIndices.size(), indices.size());
				for (int i = 0; i < indexLength; i++) {
					ExpIndex index = indices.get(i);
					ExpIndex oIndex = oIndices.get(i);
					int indexCompare = oIndex.compareTo(index);
					if (indexCompare != 0) {
						return indexCompare;
					}
				}
			}
			return Integer.compare(indices.size(), oIndices.size());
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj) {
				return true;
			}
			if (obj == null || getClass() != obj.getClass()) {
				return false;
			}
			Exp exp = (Exp)obj;
			return name.equals(exp.name) && indices.equals(exp.indices);
		}

		@Override
		public int hashCode() {
			return Objects.hash(name, indices);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy