001/* 002 * (C) Copyright 2012 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 * Anahide Tchertchian 018 */ 019package org.nuxeo.ecm.automation.core.impl; 020 021import java.util.HashMap; 022import java.util.Map; 023 024import org.nuxeo.ecm.automation.OperationException; 025import org.nuxeo.ecm.automation.OperationType; 026import org.nuxeo.ecm.automation.core.annotations.Operation; 027import org.nuxeo.runtime.model.ContributionFragmentRegistry; 028 029/** 030 * @since 5.6 031 */ 032public class OperationTypeRegistry extends ContributionFragmentRegistry<OperationType> { 033 034 /** 035 * Modifiable operation registry. Modifying the registry is using a lock and it's thread safe. Modifications are 036 * removing the cache. 037 */ 038 protected final Map<String, OperationType> operations = new HashMap<String, OperationType>(); 039 040 /** 041 * Read only cache for operation lookup. Thread safe. Not using synchronization if cache already created. 042 */ 043 protected volatile Map<String, OperationType> lookup; 044 045 @Override 046 public String getContributionId(OperationType contrib) { 047 return contrib.getId(); 048 } 049 050 public synchronized void addContribution(OperationType op, boolean replace) throws OperationException { 051 if (!replace && operations.containsKey(op.getId())) { 052 throw new OperationException("An operation is already bound to: " + op.getId() 053 + ". Use 'replace=true' to replace an existing operation"); 054 } 055 super.addContribution(op); 056 } 057 058 @Override 059 public void contributionUpdated(String id, OperationType contrib, OperationType newOrigContrib) { 060 operations.put(id, contrib); 061 for (String alias : contrib.getAliases()) { 062 operations.put(alias, contrib); 063 } 064 lookup = null; 065 } 066 067 @Override 068 public void contributionRemoved(String id, OperationType origContrib) { 069 operations.remove(id); 070 lookup = null; 071 } 072 073 @Override 074 public boolean isSupportingMerge() { 075 return false; 076 } 077 078 @Override 079 public OperationType clone(OperationType orig) { 080 throw new UnsupportedOperationException(); 081 } 082 083 @Override 084 public void merge(OperationType src, OperationType dst) { 085 throw new UnsupportedOperationException(); 086 } 087 088 // API 089 090 public OperationType getOperationType(Class<?> key) { 091 return operations.get(key.getAnnotation(Operation.class).id()); 092 } 093 094 public Map<String, OperationType> lookup() { 095 Map<String, OperationType> _lookup = lookup; 096 if (_lookup == null) { 097 synchronized (this) { 098 lookup = new HashMap<String, OperationType>(operations); 099 _lookup = lookup; 100 } 101 } 102 return _lookup; 103 } 104 105}