2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.j2ee.metadata.model.api.support.annotation;
44
import java.util.ArrayList;
45
import java.util.Collection;
46
import java.util.Collections;
47
import java.util.List;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import javax.lang.model.element.TypeElement;
51
import javax.swing.event.ChangeListener;
52
import org.netbeans.api.java.source.ElementHandle;
53
import org.netbeans.api.java.source.SourceUtils;
54
import org.netbeans.modules.j2ee.metadata.model.support.PersistentObjectList;
55
import org.openide.util.ChangeSupport;
56
import org.openide.util.RequestProcessor;
60
* @author Andrei Badea
62
public class PersistentObjectManager<T extends PersistentObject> implements JavaContextListener {
64
// XXX perhaps also initialize temporary when classpath not registered in GPR
65
// (since then there would be no events)
67
private static final Logger LOGGER = Logger.getLogger(PersistentObjectManager.class.getName());
68
private static final boolean NO_EVENTS = Boolean.getBoolean("netbeans.metadata.model.noevents"); // NOI18N
70
// XXX causes PersistentObjectManagerTest to fail; currently excluded in test/cfg-unit.xml
71
// private static final boolean NO_EVENTS = true;
73
private final AnnotationModelHelper helper;
74
private final ObjectProvider<T> provider;
75
private final PersistentObjectList<T> objectList = new PersistentObjectList<T>();
76
private final ChangeSupport changeSupport = new ChangeSupport(this);
77
private final RequestProcessor rp = new RequestProcessor("PersistentObjectManager", 1); // NOI18N
79
// not private because used in unit tests
80
boolean initialized = false;
81
boolean temporary = false;
83
static <V extends PersistentObject> PersistentObjectManager<V> create(AnnotationModelHelper helper, ObjectProvider<V> provider) {
84
PersistentObjectManager<V> pom = new PersistentObjectManager<V>(helper, provider);
86
LOGGER.log(Level.FINE, "ignoring events"); // NOI18N
88
helper.addJavaContextListener(pom);
92
private PersistentObjectManager(AnnotationModelHelper helper, ObjectProvider<T> provider) {
94
this.provider = provider;
97
public Collection<T> getObjects() {
99
List<T> result = objectList.get();
100
if (LOGGER.isLoggable(Level.FINEST)) {
101
LOGGER.log(Level.FINEST, "getObjects returning {0} objects: {1}", new Object[] { result.size(), result}); // NOI18N
103
LOGGER.log(Level.FINE, "getObjects returning {0} objects", result.size()); // NOI18N
108
private void ensureInitialized() {
110
boolean scanInProgress = SourceUtils.isScanInProgress();
111
temporary = NO_EVENTS | scanInProgress;
113
LOGGER.log(Level.FINE, "initalizing temporarily (scanInProgress: {0})", scanInProgress); // NOI18N
115
LOGGER.log(Level.FINE, "intializing"); // NOI18N
119
objects = provider.createInitialObjects();
120
} catch (InterruptedException e) {
121
LOGGER.log(Level.FINE, "initializing temporarily (createInitialObjects() throwed InterruptedException)"); // NOI18N
123
objects = Collections.emptyList();
125
LOGGER.log(Level.FINE, "created initial objects {0}", objects); // NOI18N
126
objectList.add(objects);
131
private void deinitialize() {
136
void typesAdded(Iterable<? extends ElementHandle<TypeElement>> typeHandles) {
137
// XXX assert not in AMH java context
138
LOGGER.log(Level.FINE, "typesAdded: called with {0}", typeHandles); // NOI18N
140
LOGGER.log(Level.FINE, "typesAdded: not initialized, firing change event"); // NOI18N
144
for (ElementHandle<TypeElement> typeHandle : typeHandles) {
145
TypeElement type = typeHandle.resolve(helper.getCompilationController());
147
LOGGER.log(Level.WARNING, "typesAdded: type {0} has dissapeared", typeHandle); // NOI18N
150
List<T> newObjects = provider.createObjects(type);
151
LOGGER.log(Level.FINE, "typesAdded: new objects {0}", newObjects); // NOI18N
152
if (objectList.put(typeHandle, newObjects)) {
158
void typesRemoved(Iterable<? extends ElementHandle<TypeElement>> typeHandles) {
159
// XXX assert not in AMH java context
160
LOGGER.log(Level.FINE, "typesRemoved: called with {0}", typeHandles); // NOI18N
162
LOGGER.log(Level.FINE, "typesRemoved: not initialized, firing change event"); // NOI18N
166
for (ElementHandle<TypeElement> typeHandle : typeHandles) {
167
List<T> list = objectList.remove(typeHandle);
169
LOGGER.log(Level.FINE, "typesRemoved: removing objects {0}", list); // NOI18N
175
void typesChanged(Iterable<? extends ElementHandle<TypeElement>> typeHandles) {
176
// XXX assert not in AMH java context
177
LOGGER.log(Level.FINE, "typesChanged: called with {0}", typeHandles); // NOI18N
179
LOGGER.log(Level.FINE, "typesChanged: not initialized, firing change event"); // NOI18N
183
for (ElementHandle<TypeElement> typeHandle : typeHandles) {
184
List<T> list = objectList.get(typeHandle);
186
// we have objects based on this type
187
TypeElement type = typeHandle.resolve(helper.getCompilationController());
189
LOGGER.log(Level.WARNING, "typesChanged: type {0} has dissapeared", typeHandle); // NOI18N
192
List<T> oldNewObjects = new ArrayList<T>(list);
193
boolean modified = provider.modifyObjects(type, oldNewObjects);
195
LOGGER.log(Level.FINE, "typesChanged: modified objects to {0}", oldNewObjects); // NOI18N
196
if (objectList.put(typeHandle, oldNewObjects)) {
200
LOGGER.log(Level.FINE, "typesChanged: not modifying any objects"); // NOI18N
203
// we don't have any object based on this type
204
TypeElement type = typeHandle.resolve(helper.getCompilationController());
206
LOGGER.log(Level.WARNING, "typesChanged: type {0} has dissapeared", typeHandle); // NOI18N
209
List<T> newObjects = provider.createObjects(type);
210
LOGGER.log(Level.FINE, "typesChanged: new objects {0}", newObjects); // NOI18N
211
if (objectList.put(typeHandle, newObjects)) {
218
public void addChangeListener(ChangeListener listener) {
219
changeSupport.addChangeListener(listener);
222
public void removeChangeListener(ChangeListener listener) {
223
changeSupport.removeChangeListener(listener);
226
private void fireChange() {
227
LOGGER.log(Level.FINE, "firing change event"); // NOI18N
228
if (!changeSupport.hasListeners()) {
231
rp.post(new Runnable() {
233
changeSupport.fireChange();
238
void rootsChanged() {
239
// XXX assert not in AMH java context
240
LOGGER.log(Level.FINE, "rootsChanged called"); // NOI18N
245
public void javaContextLeft() {
247
LOGGER.log(Level.FINE, "discarding temporary manager"); // NOI18N