001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.ui.ribbonconfiguration; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.slf4j.Logger; 024 025/** 026 * Helper for the ribbon, for injecting elements inside another elements' container 027 * @param <T> The type of element to inject 028 */ 029public class RibbonElementsInjectionHelper<T> 030{ 031 /** The list of elements */ 032 protected List<T> _elements; 033 034 /** Logger */ 035 protected Logger _logger; 036 037 private Map<Integer, ObjectOrderMapping> _mapping = new HashMap<>(); 038 039 /** 040 * Map a list of elements by they order to allows for elements injection 041 * @param elements The list of elements 042 * @param logger The logger 043 */ 044 public RibbonElementsInjectionHelper(List<T> elements, Logger logger) 045 { 046 _logger = logger; 047 _elements = elements; 048 049 if (elements.size() > 0) 050 { 051 for (T element : elements) 052 { 053 _mapping.put(elements.indexOf(element) + 1, new ObjectOrderMapping(element)); 054 } 055 } 056 else 057 { 058 _mapping.put(1, new ObjectOrderMapping(null)); 059 } 060 } 061 062 /** 063 * Inject an element into the list of elements 064 * @param inject The element to inject 065 * @param order The order property. 066 */ 067 public void injectElements(T inject, String order) 068 { 069 int indexOfDot = order.indexOf("."); 070 int primaryOrder = Integer.valueOf(indexOfDot > 0 ? order.substring(0, indexOfDot) : order); 071 Integer secondaryOrder = indexOfDot > 0 ? Integer.valueOf(order.substring(indexOfDot + 1)) : null; 072 if (primaryOrder > 0) 073 { 074 if (primaryOrder > _mapping.size() || !_mapping.containsKey(primaryOrder)) 075 { 076 // out of bound 077 if (_logger.isDebugEnabled()) 078 { 079 _logger.debug("TabOverrideHelper : injecting element '" + inject.toString() + "' with order '" + primaryOrder + "', but that order is out of bound. The element is injected at the end, after element '" + _mapping.get(_mapping.size()).getInitialObject() + "'"); 080 } 081 082 _mapping.get(_mapping.size()).injectObjectAfter(inject, null); 083 } 084 else 085 { 086 _mapping.get(primaryOrder).injectObjectBefore(inject, secondaryOrder); 087 088 if (_logger.isDebugEnabled()) 089 { 090 _logger.debug("TabOverrideHelper : injecting element '" + inject.toString() + "' with order '" + primaryOrder + "' before element '" + _mapping.get(primaryOrder).getInitialObject() + "'"); 091 } 092 } 093 } 094 else 095 { 096 int relativeOrder = _mapping.size() + primaryOrder; 097 if (relativeOrder < 0 || !_mapping.containsKey(relativeOrder)) 098 { 099 // out of bound 100 if (_logger.isDebugEnabled()) 101 { 102 _logger.debug("TabOverrideHelper : injecting element '" + inject.toString() + "' with order '" + primaryOrder + "', but that order is out of bound. The element is injected at the start, before element '" + _mapping.get(1).getInitialObject() + "'"); 103 } 104 105 _mapping.get(1).injectObjectBefore(inject, 0); 106 } 107 else 108 { 109 if (_logger.isDebugEnabled()) 110 { 111 _logger.debug("TabOverrideHelper : injecting element '" + inject.toString() + "' with order '" + primaryOrder + "' after element '" + _mapping.get(relativeOrder).getInitialObject() + "'"); 112 } 113 114 _mapping.get(relativeOrder).injectObjectAfter(inject, secondaryOrder); 115 } 116 } 117 } 118 119 private class ObjectOrderMapping 120 { 121 private T _initialObject; 122 private int _initialObjectIndex; 123 private List<T> _objectsBefore = new ArrayList<>(); 124 private Map<T, Integer> _objectsBeforeOrder = new HashMap<>(); 125 private List<T> _objectsAfter = new ArrayList<>(); 126 private Map<T, Integer> _objectsAfterOrder = new HashMap<>(); 127 128 public ObjectOrderMapping(T initialObject) 129 { 130 _initialObject = initialObject; 131 _initialObjectIndex = _initialObject != null ? _elements.indexOf(_initialObject) : 0; 132 } 133 134 public void injectObjectBefore(T object, Integer order) 135 { 136 if (_objectsBefore.size() == 0) 137 { 138 _objectsBefore.add(object); 139 if (order != null) 140 { 141 _objectsBeforeOrder.put(object, order); 142 } 143 144 _elements.add(_initialObject != null ? _elements.indexOf(_initialObject) : 0, object); 145 } 146 else 147 { 148 _inject(object, order, _objectsBefore, _objectsBeforeOrder); 149 } 150 _initialObjectIndex++; 151 } 152 153 public void injectObjectAfter(T object, Integer order) 154 { 155 if (_objectsAfter.size() == 0) 156 { 157 _objectsAfter.add(object); 158 if (order != null) 159 { 160 _objectsAfterOrder.put(object, order); 161 } 162 163 _elements.add(_initialObject != null ? _elements.indexOf(_initialObject) + 1 : _elements.size(), object); 164 } 165 else 166 { 167 _inject(object, order, _objectsAfter, _objectsAfterOrder); 168 } 169 } 170 171 private void _inject(T object, Integer order, List<T> objects, Map<T, Integer> objectsOrder) 172 { 173 if (order == null) 174 { 175 T lastObject = objects.get(objects.size() - 1); 176 _elements.add(_elements.indexOf(lastObject) + 1, object); 177 objects.add(object); 178 179 return; 180 } 181 182 T previous = null; 183 for (int i = 0; i < objects.size() && objectsOrder.containsKey(objects.get(i)) && objectsOrder.get(objects.get(i)) <= order; i++) 184 { 185 previous = objects.get(i); 186 } 187 188 objectsOrder.put(object, order); 189 if (previous == null) 190 { 191 T firstObject = objects.get(0); 192 _elements.add(_elements.indexOf(firstObject), object); 193 objects.add(0, object); 194 } 195 else 196 { 197 _elements.add(_elements.indexOf(previous) + 1, object); 198 objects.add(objects.indexOf(previous) + 1, object); 199 } 200 } 201 202 public T getInitialObject() 203 { 204 return _initialObject; 205 } 206 } 207}