View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.wicket.markup.html.form;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.List;
25  import org.apache.wicket.WicketRuntimeException;
26  import org.apache.wicket.extensions.markup.html.form.palette.Palette;
27  import org.apache.wicket.extensions.markup.html.form.palette.component.Recorder;
28  import org.apache.wicket.markup.html.form.IChoiceRenderer;
29  import org.apache.wicket.model.Model;
30  import org.apache.wicket.util.string.Strings;
31  
32  /**
33   * A variant of Recorder, supporting single element selection (for editing purpose, for example). <b>Note</b>: this
34   * class extends Recorder&lt;T&gt; but in fact it is a bare copy of most source code; this was done because the original
35   * class is keeping everything private.
36   *
37   * @param <T> Type of the palette
38   */
39  public class SelectableRecorder<T> extends Recorder<T> {
40  
41      private static final long serialVersionUID = -3009044376132921879L;
42  
43      private boolean attached = false;
44  
45      private static final String[] EMPTY_IDS = new String[0];
46  
47      /**
48       * Conveniently maintained array of selected ids.
49       */
50      private String[] ids;
51  
52      private String selectedId;
53  
54      public SelectableRecorder(final String id, final Palette<T> palette) {
55          super(id, palette);
56      }
57  
58      @Override
59      protected void onBeforeRender() {
60          super.onBeforeRender();
61  
62          if (!getForm().hasError()) {
63              initIds();
64          } else if (ids == null) {
65              ids = EMPTY_IDS;
66          }
67          attached = true;
68      }
69  
70      /**
71       * Synchronize ids collection from the palette's model
72       */
73      private void initIds() {
74          // construct the model string based on selection collection
75          IChoiceRenderer<? super T> renderer = getPalette().getChoiceRenderer();
76          StringBuilder modelStringBuffer = new StringBuilder();
77          Collection<T> modelCollection = getPalette().getModelCollection();
78          if (modelCollection == null) {
79              throw new WicketRuntimeException("Expected getPalette().getModelCollection() to return a non-null value."
80                      + " Please make sure you have model object assigned to the palette");
81          }
82          Iterator<T> selection = modelCollection.iterator();
83  
84          int i = 0;
85          while (selection.hasNext()) {
86              modelStringBuffer.append(renderer.getIdValue(selection.next(), i++));
87              if (selection.hasNext()) {
88                  modelStringBuffer.append(',');
89              }
90          }
91  
92          // set model and update ids array
93          String modelString = modelStringBuffer.toString();
94          setDefaultModel(new Model<>(modelString));
95          updateIds(modelString);
96      }
97  
98      public T getSelectedItem() {
99          if (selectedId == null) {
100             return null;
101         }
102 
103         IChoiceRenderer<? super T> renderer = getPalette().getChoiceRenderer();
104 
105         T selected = null;
106         for (T choice : getPalette().getChoices()) {
107             if (renderer.getIdValue(choice, 0).equals(selectedId)) {
108                 selected = choice;
109                 break;
110             }
111         }
112 
113         return selected;
114     }
115 
116     @Override
117     public List<T> getSelectedList() {
118         IChoiceRenderer<? super T> renderer = getPalette().getChoiceRenderer();
119         if (ids.length == 0) {
120             return List.of();
121         }
122 
123         List<T> selected = new ArrayList<>(ids.length);
124         for (String id : ids) {
125             for (T choice : getPalette().getChoices()) {
126                 if (renderer.getIdValue(choice, 0).equals(id)) {
127                     selected.add(choice);
128                     break;
129                 }
130             }
131         }
132         return selected;
133     }
134 
135     @Override
136     public List<T> getUnselectedList() {
137         IChoiceRenderer<? super T> renderer = getPalette().getChoiceRenderer();
138         Collection<? extends T> choices = getPalette().getChoices();
139 
140         if (choices.size() - ids.length == 0) {
141             return List.of();
142         }
143 
144         List<T> unselected = new ArrayList<>(Math.max(1, choices.size() - ids.length));
145         for (T choice : choices) {
146             final String choiceId = renderer.getIdValue(choice, 0);
147             boolean selected = false;
148             for (String id : ids) {
149                 if (id.equals(choiceId)) {
150                     selected = true;
151                     break;
152                 }
153             }
154             if (!selected) {
155                 unselected.add(choice);
156             }
157         }
158         return unselected;
159     }
160 
161     @Override
162     protected void onValid() {
163         super.onValid();
164         if (attached) {
165             updateIds();
166         }
167     }
168 
169     @Override
170     protected void onInvalid() {
171         super.onInvalid();
172         if (attached) {
173             updateIds();
174         }
175     }
176 
177     private void updateIds() {
178         updateIds(getValue());
179     }
180 
181     private void updateIds(final String value) {
182         if (Strings.isEmpty(value)) {
183             ids = EMPTY_IDS;
184         } else if (value.indexOf('|') == -1) {
185             ids = value.split(",");
186             selectedId = null;
187         } else {
188             String[] splitted = value.split("\\|");
189             selectedId = splitted[0];
190             ids = splitted[1].split(",");
191         }
192     }
193 }