All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.schema2beans.DDRegistry Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.schema2beans;

import java.util.*;

import java.beans.*;

/**
 *  The intent of this class is to provide a schema2beans graph registry,
 *  where the graphs are stored by unique name and type. Combined with
 *  the DDRegistryParser, the DDRegistry provides a sort of meta-schema2beans
 *  graph where we can ask for all the graphs of one type and ask for a
 *  parser on any set of graphs. These are the two main goals of this class.
 *
 *    1. provide a common and central place where we can keep track
 *       of all the graphs that we have created. Naming the graphs by 
 *       unique name and type allows to get either one specific graph 
 *       or a set of graphs.
 *
 *    2. provide a meta-schema2beans graph view for parsing any set of graphs. 
 *       For example, to get a parser on all the graphs of type 'ejb' 
 *       (assuming we registered graphs of this type).
 *
 *  Therefore, this class provides two kind of methods: to add/remove graphs
 *  to the registry and to create a DDRegistry parser. A DDRegistryParser is
 *  an Iterator that returns all the elements described a schema2beans tree path. 
 *
 *  The registry also provides a convenient class (DDChangeMarker) that helps
 *  keeping track of any change.
 */
public class DDRegistry extends Object {
    
    /**
     *	The goal of this class is to provide a simple way to know if a graph
     *	or a set of graphs had their content changed. The ChangeMarker can
     *	be used to implemenent a cache mechanism, in order to avoid parsing
     *	the graphs if nothing in the graph changed since the last parsing.
     *
     *	A ChangeMarker is created by the registry, ddReg.newChangeMarker().
     *	We can add to the changeMarger a BaseBean graph, a Cursor or another
     *	ChangeMarker. So, ChangeMarker can be nested, and any modification in
     *	a nested ChangeMarker would need that the upper ChangeMarker have been
     *  been modified.
     */
    public static class DDChangeMarker {
	
	private DDRegistry reg;
	private long timestamp;
	
	private ArrayList elts = null;
	
	DDChangeMarker(DDRegistry reg) {
	    this.reg = reg;
	    this.elts = new ArrayList();
	    this.timestamp = 0L;
	}
	
	
	public int size() {
	    return this.elts.size();
	}
	
	/**
	 *  If any graph of the added marker change, the current marker is
	 *  also considered changed.
	 */
	public void add(DDChangeMarker cm) {
	    if (cm == this) {
		Thread.dumpStack();
	    }
	    this.elts.add(cm);
	}
	
	/**
	 *  Add a graph to the marker list. If any change occurs in this graph
	 *  after resetMarker() is called, hasChanged() would return true.
	 */
	public void add(BaseBean b) {
	    RegEntry re = this.reg.getRegEntry(b, false);
	    if (re != null && !this.elts.contains(re)) {
		this.elts.add(re);
	    }
	}
	
	/**
	 *  Add the graph the cursor belongs to, to the marker list
	 */
	public void add(DDRegistryParser.DDCursor c) {
	    String id = this.reg.getID(c);
	    if (id != null) {
		BaseBean b = this.reg.getRoot(id);
		this.add(b);
	    }
	}
	
	/**
	 *  removal methods.
	 */
	public void remove(DDChangeMarker cm) {
	    this.elts.remove(cm);
	}
	
	public void remove(BaseBean b) {
	    RegEntry re = this.reg.getRegEntry(b, false);
	    if (re != null)
		this.elts.remove(re);
	}
	
	public void remove(DDRegistryParser.DDCursor c) {
	    String id = this.reg.getID(c);
	    if (id != null) {
		BaseBean b = this.reg.getRoot(id);
		this.remove(b);
	    }
	}

	/**
	 *  Reset the marke change time. Any change that happened before now
	 *  are ignored.
	 */
	public void resetTime() {
	    this.timestamp = System.currentTimeMillis();
	}
	
	/**
	 *  Return true if a change event happen between the last resetTime
	 *  and now.
	 */
	public boolean hasChanged() {
	    boolean b = this.hasChanged(this.timestamp);
	    return b;
	}
	
	private boolean hasChanged(long ts) {
	    for(int i=0; i ts) {
			    return true;
			}
		    }
	    }
	    return false;
	}

	/**
	 *  Dump all the registered markers
	 */
	public String dump() {
	    return this.dump(new StringBuffer(), "",	// NOI18N
			     this.timestamp).toString();
	}
	
	public StringBuffer dump(StringBuffer sb, String indent, long ts) {	// BEGIN_NOI18N
	    
	    sb.append(indent + this.toString() + "\n");
	    
	    for(int i=0; i ts) {
			    sb.append(" Changed  (bean ts:" + l 
				      + " > cm ts:" + ts );
			    //    + ") - last event: " + re.getLastEvent());
			} else {
			    sb.append(" No_Change (bean ts:" + l 
				      + " < cm ts:" + ts + ")");
			}
			sb.append("\n");
		    }
	    }
	    return sb;
	}									// END_NOI18N
	
	public String toString() {
	    return "DDChangeMarker-0x" + Integer.toHexString(this.hashCode());	// NOI18N
	}
    }
    
    /*
     *	Change event listener used by the change marker class
     */
    public class ChangeTracer implements PropertyChangeListener {
	DDRegistry 	reg;
	
	public ChangeTracer(DDRegistry reg) {
	    this.reg = reg;
	}
	
	public void propertyChange(PropertyChangeEvent e) {
	    
	    try {
		BaseBean s = (BaseBean)e.getSource();
		RegEntry re = this.reg.getRegEntry(s, false);
		re.setTimestamp();
		//String trc = 
		//    s.graphManager().getKeyPropertyName(e.getPropertyName());
		//re.setLastEvent(trc);
	    } catch(Exception ex) {
	    }
	}
    }
    
    private ArrayList		scopes;
    private ChangeTracer 	changeTracer;


    //
    public DDRegistry() {
	this.scopes = new ArrayList();
	this.changeTracer = new ChangeTracer(this);
    }
    
    /**
     *  Create a new entry in the DD graph registry. The schema2beans graph
     *  bean is added to registry using a unique name (ID), such as a unique
     *  internal identifier, and a non unique name (name), 
     *  such as a display name.
     *  
     *  Any number of non unique type can also be associated to a graph
     *  entry, see the method addType.
     *
     */
    public void createEntry(BaseBean bean, String ID, String name) {
	RegEntry entry = this.getRegEntry(bean, false);
	if (entry != null) {
	    throw new IllegalArgumentException(Common.getMessage(
	    "BeanGraphAlreadyInRegistry_msg", bean.name()));
	}
	
	entry = this.getRegEntry(ID);
	if (entry != null) {
	    throw new IllegalArgumentException(Common.getMessage(
	    "CantRegisterGraphSameID_msg", bean.name(), entry, ID));
	}
	bean.addPropertyChangeListener(this.changeTracer);
	this.scopes.add(new RegEntry(bean, ID, name));
    }

    /**
     *	Change the schema2beans graph for the unique entry ID. This method
     *  might be used if another graph should replace an existing entry.
     */
    public void updateEntry(String ID, BaseBean bean) {
	RegEntry entry = this.getRegEntry(ID);
	if (entry != null)
	    entry.setBean(bean);
	else
	    throw new IllegalArgumentException(Common.getMessage(
	    "CantUpdateGraphNotInRegistry_msg", ID));
    }
    
    /**
     *	Remove an entry in the registry.
     */
    public void removeEntry(BaseBean bean) {
	RegEntry entry = this.getRegEntry(bean, false);
	if (entry != null) {
	    entry.getBean().removePropertyChangeListener(this.changeTracer);
	    this.removeRegEntry(entry);
	}
    }
    
    /**
     *  Rename a graph entry unique ID to a new unique ID entry and new
     *  non unique name.
     */
    public void renameEntry(String oldID, String newID, String newName) {
	RegEntry entry = this.getRegEntry(oldID);
	if (entry != null) {
	    entry.setID(newID);
	    if (newName != null)
		entry.setName(newName);
	}
    }

    /**
     *  Rename a graph unique ID to a new unique ID.
     */
    public void renameEntry(String oldID, String newID) {
	this.renameEntry(oldID, newID, null);
    }

    /**
     *  Remove a registry entry.
     */
    public void removeEntry(String ID) {
	RegEntry entry = this.getRegEntry(ID);
	if (entry != null)
	    entry.getBean().removePropertyChangeListener(this.changeTracer);
	this.removeRegEntry(entry);
    }
    
    /**
     *  This return a new change marker instance, that can be used to know
     *  if any graph of the registry has changed.
     */	
    public DDChangeMarker createChangeMarker() {
	return new DDChangeMarker(this);
    }
    
    /**
     *	Return true of the specified schema2beans graph is registered with the
     *  specified type.
     */
    public boolean hasType(BaseBean bean, String type) {
	RegEntry r = this.getRegEntry(bean, false);
	if (r != null)
	    return r.hasType(type);
	return false;
    }
    
    /**
     *  Reset the change timestamp of all the registered graphs.
     */
    public void clearCache() {
	for (int i=0; i0)
	    return r[0];
	return null;
    }
    
    /**
     *	Return all the bean roots for this name (either unique name or scope)
     */
    public BaseBean[] getRoots(String s) {
	s = getGraphName(s);
	//	Try to get the root by name, then by type
	RegEntry se = this.getRegEntry(s);
	if (se == null) {
	    ArrayList list = new ArrayList();
	    for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy