
com.iofairy.tuple.TupleBase Maven / Gradle / Ivy
/*
* Copyright (C) 2021 iofairy,
*
* 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.iofairy.tuple;
import com.iofairy.except.*;
import com.iofairy.si.SI;
import com.iofairy.top.G;
import java.util.*;
/**
* Base tuple
*
* @since 0.0.1
*/
public abstract class TupleBase implements Tuple {
private static final long serialVersionUID = 10065917090L;
/**
* List of aliases. 普通别名列表。
*/
private final List aliasList = new ArrayList<>();
/**
* List of tuple aliases. TupleAlias别名列表。
*/
private final List tupleAliasList = new ArrayList<>();
/**
* Map of aliases. 别名与序号键值对
*/
private final Map alias_index = new HashMap<>();
private final static String MSG_FOR_TUPLE0_UNSUPPORTED =
G.IS_ZH_LANG ? "Tuple0不支持调用alias方法,因为Tuple0是一个空元组。"
: "The `alias` method is unsupported in Tuple0. Because Tuple0 is empty tuple. ";
private final static String MSG_FOR_STRING_ALIASES =
G.IS_ZH_LANG ? "别名未设置,请先调用 alias(String...) 或 alias(TupleAlias...) 方法设置别名。"
: "The aliases not set. Please call `alias(String...)` or `alias(TupleAlias...)` method first. ";
private final static String MSG_FOR_TUPLE_ALIASES =
G.IS_ZH_LANG ? "别名未设置,请先调用 alias(TupleAlias...) 方法设置别名。"
: "The aliases not set. Please call `alias(TupleAlias...)` method first. ";
@Override
public Tuple alias(TupleAlias... aliases) {
if (arity() == 0) throw new UnsupportedOperationException(MSG_FOR_TUPLE0_UNSUPPORTED);
clearAlias();
if (aliases == null) {
if (arity() == 1) {
alias((String[]) null);
tupleAliasList.add(null);
return this;
}
throw new NumberOfAliasesException(G.IS_ZH_LANG ? "参数`aliases`的长度不等于" + arity() + "。" : "The aliases' length is not equals " + arity() + ". ");
}
List localAliases = Arrays.asList(aliases);
Set aliasSet = new HashSet<>(localAliases);
if (localAliases.size() != aliasSet.size()) throw new AliasDuplicateException(G.IS_ZH_LANG ? "别名不能重复!" : "The `aliases` can't repeat. ");
String[] localStrAliases = localAliases.stream().map(e -> e == null ? null : e.toString()).toArray(String[]::new);
alias(localStrAliases);
tupleAliasList.addAll(localAliases);
return this;
}
@Override
public Tuple alias(String... aliases) {
if (arity() == 0) throw new UnsupportedOperationException(MSG_FOR_TUPLE0_UNSUPPORTED);
clearAlias();
if (aliases == null) {
if (arity() == 1) {
putToMapAndList(null, 0);
return this;
}
throw new NumberOfAliasesException(G.IS_ZH_LANG ? "参数`aliases`的长度不等于" + arity() + "。" : "The aliases' length is not equals " + arity() + ". ");
}
List localAliases = Arrays.asList(aliases);
Set aliasSet = new HashSet<>(localAliases);
if (localAliases.size() != aliasSet.size()) throw new AliasDuplicateException(G.IS_ZH_LANG ? "别名不能重复!" : "The `aliases` can't repeat. ");
if (arity() != aliases.length)
throw new NumberOfAliasesException(G.IS_ZH_LANG ? "参数`aliases`的长度不等于" + arity() + "。" : "The aliases' length is not equals " + arity() + ". ");
for (int i = 0; i < aliases.length; i++) putToMapAndList(aliases[i], i);
return this;
}
private void putToMapAndList(String alias, int index) {
alias_index.put(alias, index);
aliasList.add(alias);
}
@Override
public String aliasType() {
return !tupleAliasList.isEmpty() ? "tuple" : !aliasList.isEmpty() ? "string" : "null";
}
@Override
public Tuple copyAliases(Tuple tuple) {
if (tuple.arity() == arity()) {
List tempTupleAliases = tuple.getTupleAliases();
List tempAliases = tuple.getAliases();
clearAlias();
if (tempTupleAliases.isEmpty()) {
if (!tempAliases.isEmpty()) {
String[] strAliases = tempAliases.toArray(new String[0]);
alias(strAliases);
}
} else {
TupleAlias[] tupleAliases = tempTupleAliases.toArray(new TupleAlias[0]);
alias(tupleAliases);
}
return this;
}
throw new NumberOfAliasesException(G.IS_ZH_LANG ? "参数`tuple`的元素数量不等于" + arity() + "。" : "The `tuple.arity()` is not equals " + arity() + ". ");
}
@Override
public void clearAlias() {
aliasList.clear();
tupleAliasList.clear();
alias_index.clear();
}
@Override
public List getTupleAliases() {
return Collections.unmodifiableList(tupleAliasList);
}
@Override
public List getAliases() {
return Collections.unmodifiableList(aliasList);
}
@Override
public boolean aliasesEquals(Tuple tuple) {
if (tuple == null || tuple.arity() != arity() || !tuple.aliasType().equals(aliasType())) return false;
if (arity() == 0) return true;
List aliases1 = getAliases();
List aliases2 = tuple.getAliases();
// tupleAliasList 不用判断,因为 tupleAliasList 会转成 string 存储在 aliasList 中。
if (aliases1.size() != aliases2.size()) return false;
if (aliases1.isEmpty()) return true;
for (int i = 0; i < aliases1.size(); i++) if (!Objects.equals(aliases1.get(i), aliases2.get(i))) return false;
return true;
}
@Override
public R __(TupleAlias alias) {
// 这里TupleAlias没有设置不用抛异常,需要再检查字符串别名是否有设置
// if (tupleAliasList.isEmpty()) throw new AliasNotSetException(MSG_FOR_TUPLE_ALIASES);
return __(alias == null ? null : alias.toString());
}
@Override
public R __(String alias) {
if (aliasList.isEmpty()) {
throw new AliasNotSetException(MSG_FOR_STRING_ALIASES);
}
if (alias_index.containsKey(alias)) {
return element(alias_index.get(alias));
} else {
throw new AliasNotFoundException(G.IS_ZH_LANG ? "别名`" + alias + "`没有找到。" : "The alias `" + alias + "` not found. ");
}
}
@Override
public boolean containsAlias(TupleAlias alias) {
return !tupleAliasList.isEmpty() && containsAlias(alias.toString());
}
@Override
public boolean containsAlias(String alias) {
return arity() != 0 && aliasList.contains(alias);
}
@Override
public Map toMap() {
return map();
}
private Map map() {
Map tupleMap = new HashMap<>();
if (arity() == 0) return tupleMap;
for (int i = 0; i < arity(); i++) {
if (aliasList.isEmpty()) {
tupleMap.put("_" + (i + 1), element(i));
} else {
tupleMap.put(aliasList.get(i), element(i));
}
}
return tupleMap;
}
@Override
public SI toSI() {
return SI.of(this.toMap());
}
@Override
public Tuple2 elementWithTupleAlias(int n) {
if (n >= arity()) throw new IndexOutOfBoundsException("Index out of range: " + n + ", Size: " + arity());
if (tupleAliasList.isEmpty()) {
throw new AliasNotSetException(MSG_FOR_TUPLE_ALIASES);
}
TupleAlias alias = tupleAliasList.get(n);
R element = this.element(n);
return new Tuple2<>(alias, element);
}
@Override
public Tuple2 elementWithAlias(int n) {
if (n >= arity()) throw new IndexOutOfBoundsException("Index out of range: " + n + ", Size: " + arity());
if (aliasList.isEmpty()) {
throw new AliasNotSetException(MSG_FOR_STRING_ALIASES);
}
String alias = aliasList.get(n);
R element = this.element(n);
return new Tuple2<>(alias, element);
}
@Override
public String toString() {
if (arity() == 0) {
return "()";
} else {
List strList = new ArrayList<>();
for (int i = 0; i < arity(); i++) {
strList.add(G.toString((Object) element(i)));
}
return alias_index.isEmpty() ? "(" + String.join(", ", strList) + ")" : "(" + concatElement(strList) + ")";
}
}
private String concatElement(List strList) {
ArrayList tempStrList = new ArrayList<>();
for (int i = 0; i < strList.size(); i++) {
String alias = aliasList.get(i);
alias = (alias == null ? "`null`" : alias);
tempStrList.add(alias + ": " + strList.get(i));
}
return String.join(", ", tempStrList);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Tuple) {
Tuple tuple = (Tuple) obj;
if (aliasesEquals(tuple)) {
for (int i = 0; i < arity(); i++) {
if (!Objects.equals(element(i), tuple.element(i))) return false;
}
return true;
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy