The entry point for getting and setting project properties is the HashStructureNode.getProperties() method, which returns a HashStructure. Any changes made to the HashStructure are automatically persisted by the IDE in an XML format mediated by HashStructureIO. All URL objects stored in the HashStructure are automatically persisted as being relative to the Project's URL, if possible. If no relative path is possible or if the relative path involves ascending to the root of the file system, the absolute URL is persisted instead.

The root of the Project's properties is a HashStructure. Both structures can hold certain types of "leaf" properties such as String, URL, int, boolean, and a few others. Full details of the supported types are documented in HashStructure and ListStructure.

By convention, instead of storing leaf properties directly in the root HashStructure, an IDE extension writer should group properties specific to an extension together in their own HashStructure and put that into the Project's root HashStructure. This will help avoid name collisions, isolate any migration issues to the relevent sub-HashStructure, and facilitate support for cascading properties and typesafe adapters.

The Project class also distinguishes two levels of properties: shared and user-specific. "Shared" refers to those properties that are stored in the project file, which is often source-controlled and used in a team environment. If a property change needs to be pushed out to other team members using the same project file, that property must be stored as a shared property. In contrast, "user-specific" refers to a customization to a shared property that a user wants to change, usually temporariliy, without having to checkout the project from source control. The ability to keep shared and user-specific properties separate but have property lookups give precedence to user-specific property values is referred to as "cascading" properties.

There are three methods for retrieving a HashStructure, providing different angles on cascading:

Clients that only read properties should use HashStructureNode.getProperties(). Clients that write properties have an extra aspect to consider - changes to shared properties may have an impact on team development, possibly including merge conflicts on the project file. Therefore, the decision to save a shared property needs to be considered carefully with respect to team development impact. The Project API is intentionally designed to bias toward saving properties as user-specific. This design forces a developer to have to code to DataContainer.getSharedPropertiesOnly() in order to persist shared project properties.

Because project property changes tend to come in batches, there is an API method for specifying that change notifications should be temporarily buffered and fired all together sometime later. The API is HashStructureNode.applyBatchChanges(java.lang.Runnable). While the Runnable is executing, all change events are buffered rather than fired. When the runnable completes, either normally or by throwing, all change events are fired together in one large event.

The Project class is declared final. Allowing subtyping would actually decrease flexibility, since the IDE's Project file must work properly even when loaded by different combinations of IDE extensions. If Project subtyping were allowed, the persistence would become more complicated, and interoperability would be hindered rather than enhanced, since extensions would rely on typecasting, such as after calling Context.getProject(), which would fail with ClassCastException when extensions compete for what the exact subtype of the Project should be. Therefore, to avoid these design pitfalls, the Project class is final and will remain final.

Instead, we prescribe a different approach for typesafe access to project properties using adapters. To access a specific property, you attach (or wrap) an adapter to the Project and call methods on the adapter to perform the storage and retrieval operations on the underlying HashStructure. Usually, the fully-qualified name of the adapter is the name of the sub-HashStructure that the adapter operates on. Whenever possible, this is an important naming convention to follow, because it simplifies the process of locating the adapter class when you looking at the persisted project file. For example, consider this project file:

There are three "hash" elements at the first (root) level of properties. Their names, such as oracle.jdeveloper.compiler.OjcConfiguration, are actually the fully-qualified names of the HashStructureAdapter class responsible for each sub-hash. Although not technically required at the API level, this is very helpful convention to follow for making the contents of the project file easier to learn and understand.

<emp>Note:</emp> Starting 07/01/2008 the owner map is deprecated without replacement. Comments below are no longer relevant, left for reference of legacy code. All additions and updates to the owner map are now no-ops.

A project may contain children owned by other Nodes which are part of the same project. "Owned" in this context means that the owner Node has final veto power over whether a child Node can be added, removed, moved, or renamed. In the Application Navigator, owned Nodes are usually not displayed and are instead represented by a composite node for the owner.

The Node-to-owner relationship is maintained by the project and persited in the project file. Both the Node and owner must be a Node, because the NodeFactory is used to load them from the persisted data. Owner Nodes must be direct children of the Project.

getChildren

public final java.util.Iterator getChildren()

This method should not be used for getting project children. The method does not scale well when large projects are involved.

We now recommend clients use the Index Model API. This new API works asynchronously and performs very well, regardless of the project size, once the index model of the project files is constructed. See oracle.ide.index.Index#findNodes( oracle.ide.index.QueryCriteria, oracle.ide.index.ResultCallback)

canRemove

Call this method to determine if the element can be removed from this project. If the specified element is not a Node, this method returns true. If it is a node and it has an owner, it delegates the call to the Folder owner. It the node does not have an owner, implying that the project owns the node, this method returns true.

<emp>Note:</emp> With the deprecation of the owner map, all reference to owner and owner map are irrelevant.

add

Adds the node to the project, specifically adding it to the content set identified by the content set key. The supplied key must match one of the ContentProviders registered with the project. If the key is valid but the node cannot be added to that content set, the node will be added to the Resources content set, if possible.

Parameters:

node - the node to add

contentSetKey - the key that identifies the content set

Returns:

true if the node was added successfully, false if the node could not be added to the specified content set.

Throws:

java.lang.IllegalArgumentException - if contentSetKey does not identify one of the registered ContentSetProviders.

add

Adds the nodes to the project, specifically adding it to the content set identified by the content set key. The supplied key must match one of the ContentProviders registered with the project. If the key is valid but the node cannot be added to that content set, the node will be added to the Resources content set, if possible.

Parameters:

nodes - the nodes to add

contentSetKey - the key that identifies the content set

Returns:

true if all the nodes were added successfully, false if one or more nodes could not be added to the specified content set.

Throws:

java.lang.IllegalArgumentException - if contentSetKey does not identify one of the registered ContentSetProviders.

add

This method no longer has any effect on the Project. Use AddContentCommand to make sure that files appear in a project under the right content set, and also be sure that newly created files are saved (this will also trigger the UpdateMessage.CHILD_ADDED event automatically).

isDefaultProject

findChildren

@Deprecated
public final java.util.Iterator findChildren(java.lang.Class childType)

Deprecated.since 11.0 (07/01/2008)

This method should not be used for finding project children. The method does not scale well when large projects are involved.

We now recommend clients use the Index Model API. This new API works asynchronously and performs very well, regardless of the project size, once the index model of the project files is constructed. See oracle.ide.index.Index#findNodes( oracle.ide.index.QueryCriteria, oracle.ide.index.ResultCallback).

findChildren

@Deprecated
public final java.util.Iterator findChildren(java.lang.Class[] types)

Deprecated.since 11.0 (07/01/2008)

This method should not be used for finding project children. The method does not scale well when large projects are involved.

We now recommend clients use the Index Model API. This new API works asynchronously and performs very well, regardless of the project size, once the index model of the project files is constructed. See oracle.ide.index.Index#findNodes( oracle.ide.index.QueryCriteria, oracle.ide.index.ResultCallback).

removeProjectChangeListener

setCustomizedDefaults

Sets the specified HashStructure as the source for customized default values for the project. These are initialized into every Project instance as placeholder values in the Project's actual HashStructure. See HashStructure for details on what placeholders are and how they are used.

add

Deprecated.07/01/2008: owner maps are deperecated without replacement. This method is now a no-op.

Add the node to the project, specifying ownerNode as its owner. For this method to return successfully, the ownerNode must also be a Folder. If the node already had an owner in this Project when this method is called, the method does nothing.

Once this method is successful, a call to findOwner(Element) with the node as its argument will return the ownerNode.

findMyChildren

@Deprecated
public final java.util.Iterator findMyChildren(java.lang.Class childType)

Deprecated.07/01/2008

Retrieves children of a specific type owned by the project. Unlike getChildren, children owned by folders within the project will not be returned. The list of owned children is filtered to include only those children of the specified type.

We now recommend clients use the Index Model API. This new API works asynchronously and performs very well, regardless of the project size, once the index model of the project files is constructed. See oracle.ide.index.Index#findNodes( oracle.ide.index.QueryCriteria, oracle.ide.index.ResultCallback)

Parameters:

childType - the Class representing the desired type

Returns:

an Iterator over the filtered child list, guaranteed not to be null.

findMyChildren

@Deprecated
public final java.util.Iterator findMyChildren(java.lang.Class[] types)

Deprecated.

Retrieves the children that are one of the specified types owned by the project. UnlikegetChildren, children owned by folders within the project will not be returned.

Parameters:

types - an array of Class objects indicating the desired types

Returns:

an Iterator over the Project's children that includes only those elements whose type (or supertype) is one of the specified types.