## org.biojava.bio.seq.projection
Interface ProjectionContext

All Known Implementing Classes:
  ReparentContext, SimpleGappedSequence.GappedContext, SubSequence.SubProjectedFeatureContext, TranslateFlipContext

    public interface ProjectionContext

Interface that defines the projection between original features and projected features.

Note: Implementing this interface is not trivial. It is assumed that if you are implementing this, you are a power user or developer. All method documentation is aimed at those groups, not users.

## Core projection methods

This interface directly specifies a core set of methods that a ProjectionContext implementation must provide. These are needed to allow ProjectedFeatureHolder to connect to the context and for projected features to be implemented on top of the context.

All of these methods are implemented by @link ReparentContext, and it would be unwise to try to implement them again independently, but it's a free world and this is, after all, an interface. Some of the methods have contracts that are a little tricky to implement without some thought.

The methods projectFeature() and revertFeature() should be used as your exclusive means for converting features between the two views. If you have some utility method that produces projections, it /must/ be exclusively invoked from projectFeature(). Likewise, although it is tempting to cast the projected feature to Projection, and then to call getProjectedFeature(), this will break the encapsulation of the context. The only method that should do this cast is revertFeature().

## Extra projection methods

Projection methods are used by the projection engine to map projected and unprojected feature properties. They are not declared directly in this interface, but should be supplied by implementations. They will be picked up by the projection engine using introspection, and connected to projected feature instances by run-time code generation.

So that the projection methods can be found, they should all follow the same template. If a feature interface has a property `foo` of type `Bar`, then the feature interface will have the two methods: ``

     public void setFoo(Bar bar)
     public Bar getFoo()

The projection engine will be looking for a pair of methods in the context named: `public Bar projectFoo(Bar bar); public Bar revertFoo(Bar bar);` If these methods are found, then the projected feature will have get/set methods that resemble: `

     public void setFoo(Bar bar) {
       getViewedFeature().setFoo(getContext().revertFoo(bar));
     }

     public Bar getFoo() {
       return getContext().projectFoo(getViewedFeature().getFoo());
     }

` If these methods are not found, then the projected feature will have get/set methods that resembl: `

     public void setFoo(Bar bar) {
       getViewedFeature().setFoo(bar);
     }

     public Bar getFoo() {
       return getContext().getViewedFeature().getFoo();
     }

`

Only those methods defined by the interface of the unprojected feature will be mapped accross. So, if the context provides projectors for the strand property but the feature is not a stranded feature, it's projection will not have a strand property.

You should probably not be implementing these yourself. Use the standard factory methods in SequenceTools to create new sequences that are altered views of other sequences. You will probably want to instantiate @link ReparentContext or @link TranslateFlipContext to achieve the most commonly needed transformations. If you do have to implement this, extend one of these two classes. Consider extending @link ReparentContext or @link TranslateFlipContex. They do a lot of complex work for you. When projecting an original location `origLoc` to your new location `yourLoc`, be sure to make sure the decorations match. The easiest way to do this is return `origLoc.newInstance(yourLoc)`. Every ProjectionContext implementation must be a public or package-private class. This is because ProjectionEngine wires method calls from the projected features back into the context. These methods are not necessarily defined by the context interface (if they are project/revert pairs), so the class itself must be directly accessible. The ProjectionEngine creates accessory classes in the same package as the context it is using.

Since:
  1.4
Author:
  Thomas Down, Matthew Pocock

Method Summary
`void` `addChangeListener(Feature projFeat, ChangeListener cl, ChangeType ct)` Add a ChangeListener to a projected feature.
`Feature` `createFeature(Feature.Template projTempl)` Create a projected feature with properties matching the template.
`Feature` `createFeature(Feature projParent, Feature.Template projTempl)` Create a new projected feature.
`FeatureHolder` `getParent(Feature projFeat)`
`Sequence` `getSequence(Feature projFeat)` Get the sequence for a feature.
`FeatureHolder` `getUnprojectedFeatures()` Get the features before projection.
`FeatureHolder` `projectChildFeatures(Feature feature, FeatureHolder parent)` Project all features that are children of feature so that they become children of parent.
`Feature` `projectFeature(Feature feat)` Project a single feature.
`FeatureHolder` `projectFeatures(FeatureHolder features)` Project all of the features in a FeatureHolder.
`FeatureFilter` `projectFilter(FeatureFilter filt)` Transform a filter on unprojected features so that it applies to projected features.
`void` `removeChangeListener(Feature projFeat, ChangeListener cl, ChangeType ct)` Remove a ChangeListener from a projected feature.
`void` `removeFeature(Feature dyingChild)` Remove the dying child.
`void` `removeFeature(Feature projParent, Feature dyingChild)` Remove the dying child.
`Feature` `revertFeature(Feature projFeat)` Unproject a feature.
`FeatureFilter` `revertFilter(FeatureFilter filt)` Transform a filter on projected features so that it applies to unprojected features.

Method Detail

### getUnprojectedFeatures

    FeatureHolder getUnprojectedFeatures()

  Get the features before projection.

  If you are projecting all the features in some feature holder, that is what this method should return.

  Returns:
    the features before projection

### getParent

    FeatureHolder getParent(Feature projFeat)

### getSequence

    Sequence getSequence(Feature projFeat)

  Get the sequence for a feature.

  This will be the return value of `projFeat.getParent()`.

  Parameters:
    `projFeat` - the projected Feature
  Returns:
    the Sequence of the Feature

### projectFeature

    Feature projectFeature(Feature feat)

  Project a single feature.

  Parameters:
    `feat` - the Feature to project
  Returns:
    a Feature representing feat after being transformed by this context

### projectFeatures

    FeatureHolder projectFeatures(FeatureHolder features)

  Project all of the features in a FeatureHolder.

  Warning: The results of calling this method for features that are not in getUnprojectedFeatures() is not specified by this API, but it is reasonable to assume that bad things will happen.

  Parameters:
    `features` - the FeatureHolder containing the features to project
  Returns:
    a FeatureHolder containing all the features projected

### revertFeature

    Feature revertFeature(Feature projFeat)

  Unproject a feature.

  This is the inverse opperation to @link projectFeature().

  Note: The result of calling this method for a feature that is not projected through this context is not specified by this API, but it is reasonable to assume that bad things will happen.

  Parameters:
    `projFeat` - the Feature to un-project
  Returns:
    the unprojected feature

### projectFilter

    FeatureFilter projectFilter(FeatureFilter filt)

  Transform a filter on unprojected features so that it applies to projected features.

  Parameters:
    `filt` - the FeatureFilter to transform
  Returns:
    the transformed FeatureFilter

### revertFilter

    FeatureFilter revertFilter(FeatureFilter filt)

  Transform a filter on projected features so that it applies to unprojected features.

  Parameters:
    `filt` - the FeatureFilter to transform
  Returns:
    the transformed FeatureFilter

### projectChildFeatures

    FeatureHolder projectChildFeatures(Feature feature,
                                       FeatureHolder parent)

  Project all features that are children of feature so that they become children of parent.

  Parameters:
    `feature` - the Feature to project all children of
    `parent` - the new parent feature holder
  Returns:
    a FeatureHolder containing projections of all children of feature so that f.getParent() is equal to parent

### createFeature

    Feature createFeature(Feature.Template projTempl)
                          throws BioException,
                                 ChangeVetoException

  Create a projected feature with properties matching the template.

  You will probably implement this by delegating to the unprojected feature holder. It is imperative that the template properties are unprojected first so that when the newly created feature is projected, the properties match up.

  Not every projection context has fully reversible semantics. Use your discression and come up with a reasonable plan that causes least supprise to the user.

  Parameters:
    `projTempl` - the Feature.Template to instantiate
  Returns:
    a new projected Feature matching the template as closely as possible
  Throws:
    `BioException` - if there was a problem instantiating the template
    `ChangeVetoException` - if the feature creation was vetoed

### removeFeature

    void removeFeature(Feature dyingChild)
                       throws BioException,
                              ChangeVetoException

  Remove the dying child.

  Parameters:
    `dyingChild` - a projected feature to remove
  Throws:
    `BioException` - if there is an error removing the feature
    `ChangeVetoException` - if the removal of the feature was vetoed

### createFeature

    Feature createFeature(Feature projParent,
                          Feature.Template projTempl)
                          throws BioException,
                                 ChangeVetoException

  Create a new projected feature.

  See the notes for @link createFeature(Feature.Template) for implementation advice.

  Parameters:
    `projParent` - the parent for the newly created feature
    `projTempl` - the Feature.Template specifying the new feature
  Returns:
    a new ProjectedFeature that is a child of projParent
  Throws:
    `BioException` - if there was a problem creating the feature
    `ChangeVetoException` - if the creation of the feature was vetoed

### removeFeature

    void removeFeature(Feature projParent,
                       Feature dyingChild)
                       throws ChangeVetoException,
                              BioException

  Remove the dying child.

  Parameters:
    `projParent` - the projected parent Feature
    `dyingChild` - the child Feature to remove
  Throws:
    `ChangeVetoException` - if the removal of the feature was vetoed
    `BioException`

### addChangeListener

    void addChangeListener(Feature projFeat,
                           ChangeListener cl,
                           ChangeType ct)

  Add a ChangeListener to a projected feature.

  Parameters:
    `projFeat` - the projected Feature to add the listener for
    `cl` - the ChangeListener to add
    `ct` - the ChangeType to register it for

### removeChangeListener

    void removeChangeListener(Feature projFeat,
                              ChangeListener cl,
                              ChangeType ct)

  Remove a ChangeListener from a projected feature.

  Parameters:
    `projFeat` - the projected Feature to remove the listener for
    `cl` - the ChangeListener to remove
    `ct` - the ChangeType it is registered for