/******************************************************************************* * Copyright (c) 2007, 2011 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.diagram.flag; import java.nio.CharBuffer; import java.util.Arrays; import java.util.Set; import java.util.TreeSet; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.primitiverequest.OrderedSet; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; /** * @author Tuukka Lehtonen */ public class PermutativeFlagLabelingScheme implements FlagLabelingScheme { protected String initialValue; protected char min; protected char max; /** * @param initialValue * @param min * @param max */ public PermutativeFlagLabelingScheme(String initialValue, char min, char max) { this.initialValue = initialValue; this.min = min; this.max = max; } /** * Support for graph adapter construction. Only uses the first character of * both min and max parameters. * * @param initialValue * @param min * @param max */ public PermutativeFlagLabelingScheme(String initialValue, String min, String max) { this.initialValue = initialValue; this.min = min.charAt(0); this.max = max.charAt(0); } protected Set getUsedLabels(ReadGraph graph, Resource diagram) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); Layer0 L0 = Layer0.getInstance(graph); Set used = new TreeSet(NameUtils.STRING_CHARBUFFER_COMPARATOR); for (Resource element : graph.syncRequest(new OrderedSet(diagram))) { if (graph.isInstanceOf(element, DIA.Flag)) { String label = graph.getPossibleRelatedValue(element, L0.HasLabel, Bindings.STRING); if (label != null && !label.isEmpty()) used.add(label); } } return used; } @Override public String generateLabel(ReadGraph graph, Resource diagram) throws DatabaseException { CharBuffer cb = CharBuffer.allocate(10); Set used = getUsedLabels(graph, diagram); initialValue(cb); cb.limit(cb.position()); while (used.contains(cb)) { permutate(cb); cb.position(cb.limit()); } cb.rewind(); return cb.toString(); } protected void initialValue(CharBuffer cb) { cb.append(initialValue); } protected void permutate(CharBuffer cb) { permutate(cb, min, max); } /** * Takes an input char buffer and modifies it so that its last character is * set to the next value within the range [min,max]. If a character is * already equal to max, this check and modify process is continued towards * the beginning of the buffer until a character less than max is found. In * the case where all characters are already equal to max, the buffer is set * to size + 1 min characters, thus expanding the permutation space. * * For example permutating the string "AA" produces a sequence "AB", "AC", * "AD", ..., "AZ", "BA", "BB", ... */ protected void permutate(CharBuffer str, char min, char max) { // Produce the next permutation of an [{min}-{max}]* character sequence. int s = str.limit(); char[] chars = str.array(); for (int i = s - 1; i >= 0; --i) { if (chars[i] < max) { chars[i]++; for (int j = i + 1; j < s; ++j) chars[j] = min; return; } } // all permutations already in use, add more characters. str.limit(s + 1); Arrays.fill(chars, 0, s + 1, min); } }