1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates.
   3  * All rights reserved. Use is subject to license terms.
   4  *
   5  * This file is available and licensed under the following license:
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  *  - Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *  - Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in
  15  *    the documentation and/or other materials provided with the distribution.
  16  *  - Neither the name of Oracle Corporation nor the names of its
  17  *    contributors may be used to endorse or promote products derived
  18  *    from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 package com.oracle.javafx.scenebuilder.kit.fxom;
  34 
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.Map;
  38 import java.util.Set;
  39 
  40 /**
  41  *
  42  */
  43 class FxIdCollector {
  44 
  45     private final Set<String> fxIds = new HashSet<>();
  46     private Map<String, Integer> nextIndexes ; // Created lazily
  47 
  48     public FxIdCollector(Set<String> fxIds) {
  49         assert fxIds != null;
  50         this.fxIds.addAll(fxIds);
  51     }
  52 
  53     public FxIdCollector(FXOMDocument fxomDocument) {
  54         this(fxomDocument.collectFxIds().keySet());
  55     }
  56 
  57     public String importFxId(String sourceFxId) {
  58         assert sourceFxId != null;
  59 
  60         final String result;
  61         if (fxIds.contains(sourceFxId)) {
  62             if (nextIndexes == null) {
  63                 createNextIndexes();
  64                 assert nextIndexes != null;
  65             }
  66             final PrefixSuffix pf = new PrefixSuffix(sourceFxId);
  67             final Integer nextIndex = nextIndexes.get(pf.getPrefix());
  68             assert nextIndex != null;
  69             result = pf.getPrefix() + nextIndex;
  70         } else {
  71             result = sourceFxId;
  72         }
  73 
  74         fxIds.add(result);
  75         if (nextIndexes != null) {
  76             updateNextIndexes(result);
  77         }
  78 
  79         return result;
  80     }
  81 
  82 
  83     /*
  84      * Private
  85      */
  86 
  87     private void createNextIndexes() {
  88         nextIndexes = new HashMap<>();
  89 
  90         for (String fxId : fxIds) {
  91             updateNextIndexes(fxId);
  92         }
  93     }
  94 
  95 
  96     private void updateNextIndexes(String fxId) {
  97         assert nextIndexes != null;
  98 
  99         final PrefixSuffix pf = new PrefixSuffix(fxId);
 100         final Integer nextIndex = nextIndexes.get(pf.getPrefix());
 101         if ((nextIndex == null) || (pf.getSuffix() >= nextIndex)) {
 102             nextIndexes.put(pf.getPrefix(), pf.getSuffix()+1);
 103         }
 104     }
 105 
 106 
 107 
 108     private static class PrefixSuffix {
 109         private final String prefix;
 110         private final int suffix;
 111 
 112         public PrefixSuffix(String fxId) {
 113             assert fxId != null;
 114             assert fxId.isEmpty() == false;
 115 
 116             int endIndex = fxId.length();
 117             while ((endIndex >= 1) && Character.isDigit(fxId.charAt(endIndex-1))) {
 118                 endIndex--;
 119             }
 120             if (endIndex < fxId.length()) {
 121                 this.prefix = fxId.substring(0, endIndex);
 122                 this.suffix = Integer.parseInt(fxId.substring(endIndex));
 123             } else {
 124                 this.prefix = fxId;
 125                 this.suffix = -1;
 126             }
 127         }
 128 
 129         public String getPrefix() {
 130             return prefix;
 131         }
 132 
 133         public int getSuffix() {
 134             return suffix;
 135         }
 136 
 137         @Override
 138         public String toString() {
 139             return (suffix == -1) ? prefix : prefix+suffix;
 140         }
 141     }
 142 }