001/* 002 * (C) Copyright 2018 Nuxeo (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 * pierre 018 */ 019package org.nuxeo.runtime.model; 020 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.LinkedHashMap; 026import java.util.List; 027import java.util.Map; 028import java.util.Objects; 029import java.util.stream.Collectors; 030 031import org.apache.logging.log4j.LogManager; 032import org.apache.logging.log4j.Logger; 033 034/** 035 * Default generic descriptor registry. 036 * <p> 037 * It handles (un)registering and merged retrieval. 038 * <p> 039 * Merge algorithm depends on {@code Descriptor} implementations. 040 * <p> 041 * 042 * @since 10.3 043 */ 044@SuppressWarnings("unchecked") 045public class DescriptorRegistry { 046 047 private static final Logger log = LogManager.getLogger(DescriptorRegistry.class); 048 049 // target -> xp -> id -> list of descriptors 050 protected Map<String, Map<String, Map<String, List<Descriptor>>>> descriptors = new HashMap<>(); 051 052 public <T extends Descriptor> T getDescriptor(String target, String xp, String id) { 053 return (T) merge(descriptors.getOrDefault(target, Collections.emptyMap()) 054 .getOrDefault(xp, Collections.emptyMap()) 055 .getOrDefault(id, Collections.emptyList())); 056 057 } 058 059 public <T extends Descriptor> List<T> getDescriptors(String target, String xp) { 060 return (List<T>) descriptors.getOrDefault(target, Collections.emptyMap()) 061 .getOrDefault(xp, Collections.emptyMap()) 062 .values() 063 .stream() 064 .map(this::merge) 065 .filter(Objects::nonNull) 066 .collect(Collectors.toList()); 067 } 068 069 public boolean register(String target, String xp, Descriptor descriptor) { 070 log.debug("Register {} to {}/{}", descriptor.getId(), target, xp); 071 return descriptors.computeIfAbsent(target, k -> new HashMap<>()) 072 .computeIfAbsent(xp, k -> new LinkedHashMap<>()) 073 .computeIfAbsent(descriptor.getId(), k -> new ArrayList<>()) 074 .add(descriptor); 075 076 } 077 078 public boolean unregister(String target, String xp, Descriptor descriptor) { 079 log.debug("Unregister {} from {}/{}", descriptor.getId(), target, xp); 080 return descriptors.getOrDefault(target, Collections.emptyMap()) 081 .getOrDefault(xp, Collections.emptyMap()) 082 .getOrDefault(descriptor.getId(), Collections.emptyList()) 083 .remove(descriptor); 084 } 085 086 protected <T extends Descriptor> T merge(Collection<T> descriptors) { 087 T descriptor = null; 088 for (T d : descriptors) { 089 if (d.doesRemove()) { 090 descriptor = null; 091 } else { 092 descriptor = descriptor == null ? d : (T) descriptor.merge(d); 093 } 094 } 095 return descriptor; 096 } 097 098 public void clear() { 099 descriptors.clear(); 100 } 101 102}