/* * Copyright (C) Yutaka Matsuno 2010-2012 All rights reserved. */ package net.dependableos.dcase.diagram.common.util; import static net.dependableos.dcase.diagram.common.constant.SystemDefinitionConst.COLLECTION_INITIAL_CAPACITY; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.dependableos.dcase.Argument; import net.dependableos.dcase.BasicLink; import net.dependableos.dcase.BasicNode; import net.dependableos.dcase.diagram.common.exception.DcaseRuntimeException; import net.dependableos.dcase.diagram.common.model.LinkType; import net.dependableos.dcase.diagram.common.model.NodeType; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; /** * Initializes the name of a node or a link. */ public class NamePropertyAutoCreator { /** * the maximum value of sequence number. */ private static final int MAX_NUMBER = Integer.MAX_VALUE; /** * the minimum value of sequence number. */ private static final int MIN_NUMBER = 1; /** * the map of the prefixes for the nodes. */ private static final Map<NodeType, String> NODE_PREFIX_MAP; /** * the map of the prefixes for the links. */ private static final Map<LinkType, String> LINK_PREFIX_MAP; /** * the regular expression pattern. */ private static final Pattern NAME_PROPERTY_PATTERN; static { // initializes the prefixes for the nodes. NODE_PREFIX_MAP = new HashMap<NodeType, String>(); NODE_PREFIX_MAP.put(NodeType.GOAL, TermsMessages.NamePropertyAutoCreator_0); NODE_PREFIX_MAP.put(NodeType.STRATEGY, TermsMessages.NamePropertyAutoCreator_1); NODE_PREFIX_MAP.put(NodeType.EVIDENCE, TermsMessages.NamePropertyAutoCreator_2); NODE_PREFIX_MAP.put(NodeType.UNDEVELOPED, TermsMessages.NamePropertyAutoCreator_3); NODE_PREFIX_MAP.put(NodeType.CONTEXT, TermsMessages.NamePropertyAutoCreator_4); NODE_PREFIX_MAP.put(NodeType.MONITOR, TermsMessages.NamePropertyAutoCreator_5); NODE_PREFIX_MAP.put(NodeType.JUSTIFICATION, TermsMessages.NamePropertyAutoCreator_6); NODE_PREFIX_MAP.put(NodeType.SYSTEM, TermsMessages.NamePropertyAutoCreator_7); NODE_PREFIX_MAP.put(NodeType.POLICY, TermsMessages.NamePropertyAutoCreator_8); NODE_PREFIX_MAP.put(NodeType.USERDEF001, TermsMessages.NamePropertyAutoCreator_9); NODE_PREFIX_MAP.put(NodeType.USERDEF002, TermsMessages.NamePropertyAutoCreator_10); NODE_PREFIX_MAP.put(NodeType.USERDEF003, TermsMessages.NamePropertyAutoCreator_11); NODE_PREFIX_MAP.put(NodeType.USERDEF004, TermsMessages.NamePropertyAutoCreator_12); NODE_PREFIX_MAP.put(NodeType.USERDEF005, TermsMessages.NamePropertyAutoCreator_13); NODE_PREFIX_MAP.put(NodeType.USERDEF006, TermsMessages.NamePropertyAutoCreator_14); // initializes the prefixes for the links. LINK_PREFIX_MAP = new HashMap<LinkType, String>(); LINK_PREFIX_MAP.put(LinkType.BASIC_LINK, TermsMessages.NamePropertyAutoCreator_15); // initializes the regular expression pattern. NAME_PROPERTY_PATTERN = Pattern.compile("(" //$NON-NLS-1$ + StringUtil.join(NODE_PREFIX_MAP.values(), "|") + "|" //$NON-NLS-1$ //$NON-NLS-2$ + StringUtil.join(LINK_PREFIX_MAP.values(), "|") + ")(\\d+)", //$NON-NLS-1$ //$NON-NLS-2$ Pattern.CASE_INSENSITIVE); } /** * the map that manages current sequence number. */ private Map<String, Integer> currentMaxNumberMap; /** * the map that manages all sequence numbers. */ private Map<String, SortedSet<Integer>> allNumbersMap; /** * the map that manages sequence numbers those are created by this object. */ private Map<String, List<Integer>> usedNumbersMap; /** * A constructor. */ public NamePropertyAutoCreator() { } /** * Loads the diagram. * * @param argument the argument of the diagram. */ public void loadDiagram(Argument argument) { // initializes the maps. currentMaxNumberMap = new HashMap<String, Integer>(); allNumbersMap = null; usedNumbersMap = new HashMap<String, List<Integer>>(); // gets the current sequence number and sequence numbers those are created by this object. EList<BasicNode> nodeList = argument.getRootBasicNode(); for (BasicNode node : nodeList) { saveNumbers(node.getName()); } EList<BasicLink> linkList = argument.getRootBasicLink(); for (BasicLink link : linkList) { saveNumbers(link.getName()); } } /** * Saves the sequence number of the name to the map. * * @param name the name */ private void saveNumbers(String name) { if (name == null) { return; } Matcher matcher = NAME_PROPERTY_PATTERN.matcher(name); if (matcher.matches()) { String prefix = matcher.group(1); // gets the sequence number int number = 0; try { number = Integer.parseInt(matcher.group(2)); } catch (NumberFormatException nfe) { return; } if (number < MIN_NUMBER) { return; } // saves the number. saveUsedNumber(prefix, number); // tests whether the number is larger than the maximum. Integer currentMaxNumberObj = currentMaxNumberMap.get(prefix); if (currentMaxNumberObj == null || number > currentMaxNumberObj.intValue()) { currentMaxNumberMap.put(prefix, Integer.valueOf(number)); } } } /** * Returns the initial name. * * @param eObject a node or a link. * @return the name. */ public String getInitialName(EObject eObject) { // gets the prefix. String prefix = null; if (eObject instanceof BasicNode) { NodeType nodeType = NodeType.getNodeType((BasicNode) eObject); prefix = NODE_PREFIX_MAP.get(nodeType); } else if (eObject instanceof BasicLink) { prefix = LINK_PREFIX_MAP.get(LinkType.BASIC_LINK); } if (prefix == null) { return null; } // gets and updates the current number. int nextNumber = 0; try { nextNumber = getNextNumber(prefix); } catch (DcaseRuntimeException dre) { // failed to get or update the current number. return null; } // returns the initial name. return prefix + String.valueOf(nextNumber); } /** * Updates and Returns the current number. * * @param prefix the prefix. * @return the current number */ private int getNextNumber(String prefix) { // the current number is not found. Integer currentMaxNumberObj = currentMaxNumberMap.get(prefix); if (currentMaxNumberObj == null) { currentMaxNumberMap.put(prefix, Integer.valueOf(MIN_NUMBER)); saveUsedNumber(prefix, MIN_NUMBER); return MIN_NUMBER; } int currentMaxNumber = currentMaxNumberObj.intValue(); int nextNumber = 0; // the number is the maximum. if (currentMaxNumber == MAX_NUMBER) { // creates the map that manages all numbers. if (allNumbersMap == null) { allNumbersMap = new HashMap<String, SortedSet<Integer>>(); } SortedSet<Integer> sortedAllNumbers = allNumbersMap.get(prefix); if (sortedAllNumbers == null) { sortedAllNumbers = createSortedNumbers(prefix); } nextNumber = MIN_NUMBER; for (Integer sortedNumber : sortedAllNumbers) { if (nextNumber != sortedNumber.intValue()) { break; } else if (nextNumber == MAX_NUMBER) { throw new DcaseRuntimeException(null, null, null, 0, MessageTypeImpl.UNDEFINED); } nextNumber++; } sortedAllNumbers.add(Integer.valueOf(nextNumber)); allNumbersMap.put(prefix, sortedAllNumbers); } else { // updates the number. nextNumber = ++currentMaxNumber; currentMaxNumberMap.put(prefix, Integer.valueOf(currentMaxNumber)); saveUsedNumber(prefix, nextNumber); } return nextNumber; } /** * Save the number. * * @param prefix the prefix. * @param number the number. */ private void saveUsedNumber(String prefix, int number) { List<Integer> usedNumberSet = usedNumbersMap.get(prefix); if (usedNumberSet == null) { usedNumberSet = new ArrayList<Integer>(COLLECTION_INITIAL_CAPACITY); } usedNumberSet.add(Integer.valueOf(number)); usedNumbersMap.put(prefix, usedNumberSet); } /** * Creates the sorted numbers. * * @param prefix the prefix. * @return the sorted numbers. */ private SortedSet<Integer> createSortedNumbers(String prefix) { SortedSet<Integer> sortedAllNumbers = new TreeSet<Integer>(); List<Integer> usedNumbers = usedNumbersMap.get(prefix); sortedAllNumbers.addAll(usedNumbers); return sortedAllNumbers; } }