001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Florent Guillaume
018 *     Kevin Leturc
019 */
020package org.nuxeo.ecm.core.storage.dbs;
021
022import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_PREFIX;
023
024import java.io.Serializable;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028import java.util.Map.Entry;
029
030import org.nuxeo.ecm.core.storage.State;
031
032/**
033 * Function to flatten and convert {@link State} into NXQL {@link Map}<{@link String}, {@link Serializable}>.
034 *
035 * @since 8.3
036 */
037public class DBSStateFlattener {
038
039    public static Map<String, Serializable> flatten(State state) {
040        Map<String, Serializable> map = new HashMap<>();
041        flatten(map, state, null);
042        return map;
043    }
044
045    private static void flatten(Map<String, Serializable> map, State state, String prefix) {
046        for (Entry<String, Serializable> en : state.entrySet()) {
047            String key = en.getKey();
048            Serializable value = en.getValue();
049            String name;
050            if (key.startsWith(KEY_PREFIX)) {
051                name = DBSSession.convToNXQL(key);
052                if (name == null) {
053                    // present in state but not returned to caller
054                    continue;
055                }
056            } else {
057                name = key;
058            }
059            name = prefix == null ? name : prefix + name;
060            if (value instanceof State) {
061                flatten(map, (State) value, name + '/');
062            } else if (value instanceof List) {
063                String nameSlash = name + '/';
064                int i = 0;
065                for (Object v : (List<?>) value) {
066                    if (v instanceof State) {
067                        flatten(map, (State) v, nameSlash + i + '/');
068                    } else {
069                        map.put(nameSlash + i, (Serializable) v);
070                    }
071                    i++;
072                }
073            } else if (value instanceof Object[]) {
074                String nameSlash = name + '/';
075                int i = 0;
076                for (Object v : (Object[]) value) {
077                    map.put(nameSlash + i, (Serializable) v);
078                    i++;
079                }
080            } else {
081                map.put(name, value);
082            }
083        }
084    }
085
086}