/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2014, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.activiti.behavior; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import commons.Named; import org.activiti.engine.delegate.Expression; import org.activiti.engine.impl.bpmn.parser.FieldDeclaration; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import static com.google.common.base.Functions.compose; import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.not; import static com.google.common.base.Predicates.notNull; import static com.google.common.collect.Collections2.filter; import static com.google.common.collect.Collections2.transform; import static com.google.common.collect.ImmutableList.copyOf; import static com.google.common.collect.Maps.uniqueIndex; final class TaskFields { final ImmutableMap<String, FieldDeclaration> fields; final Set<String> validNames = new HashSet<String>(); TaskFields(List<FieldDeclaration> fields) { this.fields = uniqueIndex(fields, compose(new Unify(), new Names())); } public <T extends Enum<T> & Named> Field<T> named(Class<T> type, String name, String... aliases) { return next(new EnumFieldType<T>(name, type), aliases); } public Field<Integer> integer(int defaultValue, String name, String... aliases) { return next(new IntegerFieldType(name, defaultValue), aliases); } public Field<Set<String>> optional(String name, String... aliases) { return next(new SetFieldType(name, Usage.OPTIONAL), aliases); } public Field<String> required(String name, String... aliases) { return next(new StringFieldType(name, Usage.REQUIRED), aliases); } public <T> Field<T> next(FieldType<T> type, String... aliases) { Collection<String> unifiedNames = unifyNames(type.getName(), aliases); validNames.addAll(unifiedNames); Collection<FieldDeclaration> declarations = Maps.filterKeys(fields, in(unifiedNames)).values(); if (declarations.size() > 1) { throw new IllegalArgumentException( "Дублирование поля {" + Joiner.on(" | ").join(transform(declarations, new Names())) + "}" ); } Collection<Expression> expressions = filter(transform(declarations, new Values()), notNull()); Expression expression; if (expressions.isEmpty()) { if (type.getUsage() == Usage.REQUIRED) { throw new IllegalArgumentException("Пропущено обязательное поле {" + type.getName() + "}, альтернативные названия {" + Joiner.on(" | ").join(aliases) + "}"); } expression = null; } else { expression = expressions.iterator().next(); } return type.createField(expression); } public void verify() { Collection<FieldDeclaration> declarations = Maps.filterKeys(fields, not(in(validNames))).values(); if (!declarations.isEmpty()) { throw new IllegalArgumentException( "Неизвестные поля {" + Joiner.on(" | ").join(transform(declarations, new Names())) + "}" ); } } private <T> Collection<String> unifyNames(String name, String[] aliases) { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); builder.add(name); builder.addAll(copyOf(aliases)); return Collections2.transform(builder.build(), new Unify()); } final static class Names implements Function<FieldDeclaration, String> { @Override public String apply(FieldDeclaration field) { return field.getName(); } } final static class Values implements Function<FieldDeclaration, Expression> { @Override public Expression apply(FieldDeclaration field) { return (Expression) field.getValue(); } } final static class Unify implements Function<String, String> { @Override public String apply(String string) { return Joiner.on("").join(Splitter.on(' ').omitEmptyStrings().trimResults().split(string.toLowerCase())); } } }