Package: CacheLookupEngine$Node

CacheLookupEngine$Node

nameinstructionbranchcomplexitylinemethod
CacheLookupEngine.Node()
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2015 Obeo.
3: * All rights reserved. This program and the accompanying materials
4: * are made available under the terms of the Eclipse Public License v1.0
5: * which accompanies this distribution, and is available at
6: * http://www.eclipse.org/legal/epl-v10.html
7: *
8: * Contributors:
9: * Obeo - initial API and implementation
10: *******************************************************************************/
11: package org.eclipse.acceleo.query.runtime.lookup.basic;
12:
13: import java.util.HashMap;
14: import java.util.Map;
15:
16: import org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment;
17: import org.eclipse.acceleo.query.runtime.IService;
18: import org.eclipse.acceleo.query.runtime.ServiceRegistrationResult;
19: import org.eclipse.acceleo.query.runtime.impl.JavaMethodService;
20: import org.eclipse.acceleo.query.validation.type.IType;
21:
22: /**
23: * Lookup engine are used to retrieve services from a name and a set of arguments. This implementation cache
24: * service lookup result.
25: *
26: * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
27: */
28: public class CacheLookupEngine extends BasicLookupEngine {
29:
30:         /**
31:          * No service marker.
32:          */
33:         private static final IService NO_SERVICE = new JavaMethodService(null, null);
34:
35:         /**
36:          * A node of the cache forest.
37:          *
38:          * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
39:          */
40:         private static final class Node {
41:
42:                 /**
43:                  * Children (parameter {@link IType} to next {@link Node}).
44:                  */
45:                 private final Map<IType, Node> children = new HashMap<IType, Node>();
46:
47:                 /**
48:                  * The {@link IService} if any, <code>null</code> otherwise.
49:                  */
50:                 private IService service;
51:         }
52:
53:         /**
54:          * The cache forest.
55:          */
56:         private final Map<String, Node> cache = new HashMap<String, Node>();
57:
58:         /**
59:          * Constructor.
60:          *
61:          * @param queryEnvironment
62:          * the {@link IReadOnlyQueryEnvironment}
63:          */
64:         public CacheLookupEngine(IReadOnlyQueryEnvironment queryEnvironment) {
65:                 super(queryEnvironment);
66:         }
67:
68:         @Override
69:         public ServiceRegistrationResult registerService(IService service) {
70:                 cache.clear();
71:                 return super.registerService(service);
72:         }
73:
74:         @Override
75:         public IService lookup(String name, IType[] argumentTypes) {
76:                 final IService result;
77:
78:                 final Node cachedNode = getNodeFromCache(name, argumentTypes);
79:                 if (cachedNode != null) {
80:                         if (cachedNode.service == NO_SERVICE) {
81:                                 result = null;
82:                         } else if (cachedNode.service == null) {
83:                                 result = super.lookup(name, argumentTypes);
84:                                 cachedNode.service = result;
85:                         } else {
86:                                 result = cachedNode.service;
87:                         }
88:                 } else {
89:                         result = super.lookup(name, argumentTypes);
90:                         cacheService(name, argumentTypes, result);
91:                 }
92:
93:                 return result;
94:         }
95:
96:         /**
97:          * Caches the given {@link IService} for the given argument types.
98:          *
99:          * @param name
100:          * the {@link IService} name
101:          * @param argumentTypes
102:          * argument types
103:          * @param service
104:          * the {@link IService} to cache
105:          */
106:         private void cacheService(String name, IType[] argumentTypes, IService service) {
107:                 Node currentNode = cache.get(name);
108:                 if (currentNode == null) {
109:                         currentNode = new Node();
110:                         cache.put(name, currentNode);
111:                 }
112:                 for (IType type : argumentTypes) {
113:                         Node nextNode = currentNode.children.get(type);
114:                         if (nextNode == null) {
115:                                 nextNode = new Node();
116:                                 currentNode.children.put(type, nextNode);
117:                         }
118:                         currentNode = nextNode;
119:                 }
120:                 if (service == null) {
121:                         currentNode.service = NO_SERVICE;
122:                 } else {
123:                         currentNode.service = service;
124:                 }
125:         }
126:
127:         /**
128:          * Gets the {@link Node} from the cache corresponding to the given name and parameter types.
129:          *
130:          * @param name
131:          * the service name
132:          * @param argumentTypes
133:          * the argument types
134:          * @return the {@link Node} from the cache corresponding to the given name and parameter types if any,
135:          * <code>null</code> otherwise
136:          */
137:         private Node getNodeFromCache(String name, IType[] argumentTypes) {
138:                 final Node result;
139:
140:                 Node currentNode = cache.get(name);
141:                 if (currentNode != null) {
142:                         for (IType type : argumentTypes) {
143:                                 currentNode = currentNode.children.get(type);
144:                                 if (currentNode == null) {
145:                                         break;
146:                                 }
147:                         }
148:                         result = currentNode;
149:                 } else {
150:                         result = null;
151:                 }
152:
153:                 return result;
154:         }
155:
156:         @Override
157:         public IService removeService(IService service) {
158:                 cache.clear();
159:                 return super.removeService(service);
160:         }
161:
162: }