Program: 154014
Project: 154014
Buggy source:
/** 
 * Implementation of <code>PropertyChangeListener</code>. <p> When invoked with an event which is an instance of <code>RenderingChangeEvent</code> or <code>CollectionChangeEvent</code> emitted by a <code>RenderedOp</code> or <code>CollectionOp</code>, respectively, the node will respond by re-rendering itself while retaining any tiles possible.  It will respond to an "InvalidRegion" event emitted by a source <code>RenderedImage</code> in a manner similar to that applied for <code>RenderingChangeEvent</code>s.
 * @see TiledImage#propertyChange
 * @since JAI 1.1
 */
public synchronized void propertyChange(PropertyChangeEvent evt){
  Object evtSrc=evt.getSource();
  Vector nodeSources=nodeSupport.getParameterBlock().getSources();
  String propName=evt.getPropertyName().toLowerCase();
  if (theImage != null && ((evt instanceof PropertyChangeEventJAI && evtSrc == this && !(evt instanceof PropertySourceChangeEvent) && nodeEventNames.contains(propName)) || ((evt instanceof RenderingChangeEvent || evt instanceof CollectionChangeEvent || (evt instanceof PropertyChangeEventJAI && evtSrc instanceof RenderedImage && propName.equals("String_Node_Str"))) && nodeSources.contains(evtSrc)))) {
    PlanarImage theOldImage=theImage;
    boolean fireEvent=false;
    Shape invalidRegion=null;
    if (evtSrc == this && (propName.equals("String_Node_Str") || propName.equals("String_Node_Str"))) {
      fireEvent=true;
      theImage=null;
    }
 else     if (evt instanceof RenderingChangeEvent || (evtSrc instanceof RenderedImage && propName.equals("String_Node_Str"))) {
      fireEvent=true;
      Shape srcInvalidRegion=null;
      if (evt instanceof RenderingChangeEvent) {
        RenderingChangeEvent rcEvent=(RenderingChangeEvent)evt;
        srcInvalidRegion=rcEvent.getInvalidRegion();
        if (srcInvalidRegion == null) {
          srcInvalidRegion=((PlanarImage)rcEvent.getOldValue()).getBounds();
        }
      }
 else {
        srcInvalidRegion=(Shape)evt.getNewValue();
        if (srcInvalidRegion == null) {
          RenderedImage rSrc=(RenderedImage)evtSrc;
          srcInvalidRegion=new Rectangle(rSrc.getMinX(),rSrc.getMinY(),rSrc.getWidth(),rSrc.getHeight());
        }
      }
      if (!(theImage instanceof OpImage)) {
        theImage=null;
      }
 else {
        OpImage oldOpImage=(OpImage)theImage;
        Rectangle srcInvalidBounds=srcInvalidRegion.getBounds();
        if (srcInvalidBounds.isEmpty()) {
          int x=oldOpImage.tileXToX(oldOpImage.getMinTileX());
          int y=oldOpImage.tileYToY(oldOpImage.getMinTileY());
          int w=oldOpImage.getNumXTiles() * oldOpImage.getTileWidth();
          int h=oldOpImage.getNumYTiles() * oldOpImage.getTileHeight();
          Rectangle tileBounds=new Rectangle(x,y,w,h);
          Rectangle imageBounds=oldOpImage.getBounds();
          if (!tileBounds.equals(imageBounds)) {
            Area tmpArea=new Area(tileBounds);
            tmpArea.subtract(new Area(imageBounds));
            srcInvalidRegion=tmpArea;
            srcInvalidBounds=srcInvalidRegion.getBounds();
          }
        }
        boolean saveAllTiles=false;
        ArrayList validTiles=null;
        if (srcInvalidBounds.isEmpty()) {
          invalidRegion=srcInvalidRegion;
          saveAllTiles=true;
        }
 else {
          int idx=nodeSources.indexOf(evtSrc);
          Rectangle dstRegionBounds=oldOpImage.mapSourceRect(srcInvalidBounds,idx);
          if (dstRegionBounds == null) {
            dstRegionBounds=oldOpImage.getBounds();
          }
          Point[] indices=getTileIndices(dstRegionBounds);
          int numIndices=indices != null ? indices.length : 0;
          GeneralPath gp=null;
          for (int i=0; i < numIndices; i++) {
            if (i % 1000 == 0 && gp != null)             gp=new GeneralPath(new Area(gp));
            Rectangle dstRect=getTileRect(indices[i].x,indices[i].y);
            Rectangle srcRect=oldOpImage.mapDestRect(dstRect,idx);
            if (srcRect == null) {
              gp=null;
              break;
            }
            if (srcInvalidRegion.intersects(srcRect)) {
              if (gp == null) {
                gp=new GeneralPath(dstRect);
              }
 else {
                gp.append(dstRect,false);
              }
            }
 else {
              if (validTiles == null) {
                validTiles=new ArrayList();
              }
              validTiles.add(indices[i]);
            }
          }
          invalidRegion=(gp == null) ? null : new Area(gp);
        }
        theImage=null;
        TileCache oldCache=oldOpImage.getTileCache();
        if (oldCache != null && (saveAllTiles || validTiles != null)) {
          createRendering();
          if (theImage instanceof OpImage && ((OpImage)theImage).getTileCache() != null) {
            OpImage newOpImage=(OpImage)theImage;
            TileCache newCache=newOpImage.getTileCache();
            Object tileCacheMetric=newOpImage.getTileCacheMetric();
            if (saveAllTiles) {
              Raster[] tiles=oldCache.getTiles(oldOpImage);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                int tx=newOpImage.XToTileX(tile.getMinX());
                int ty=newOpImage.YToTileY(tile.getMinY());
                newCache.add(newOpImage,tx,ty,tile,tileCacheMetric);
              }
            }
 else {
              int numValidTiles=validTiles.size();
              for (int i=0; i < numValidTiles; i++) {
                Point tileIndex=(Point)validTiles.get(i);
                Raster tile=oldCache.getTile(oldOpImage,tileIndex.x,tileIndex.y);
                if (tile != null) {
                  newCache.add(newOpImage,tileIndex.x,tileIndex.y,tile,tileCacheMetric);
                }
              }
            }
          }
        }
      }
    }
 else {
      ParameterBlock oldPB=null;
      ParameterBlock newPB=null;
      boolean checkInvalidRegion=false;
      if (propName.equals("String_Node_Str")) {
        oldPB=(ParameterBlock)evt.getOldValue();
        newPB=(ParameterBlock)evt.getNewValue();
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        Vector params=nodeSupport.getParameterBlock().getParameters();
        oldPB=new ParameterBlock((Vector)evt.getOldValue(),params);
        newPB=new ParameterBlock((Vector)evt.getNewValue(),params);
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        oldPB=new ParameterBlock(nodeSources,(Vector)evt.getOldValue());
        newPB=new ParameterBlock(nodeSources,(Vector)evt.getNewValue());
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        oldPB=newPB=nodeSupport.getParameterBlock();
        checkInvalidRegion=true;
      }
 else       if (evt instanceof CollectionChangeEvent) {
        int collectionIndex=nodeSources.indexOf(evtSrc);
        Vector oldSources=(Vector)nodeSources.clone();
        Vector newSources=(Vector)nodeSources.clone();
        oldSources.set(collectionIndex,evt.getOldValue());
        newSources.set(collectionIndex,evt.getNewValue());
        Vector params=nodeSupport.getParameterBlock().getParameters();
        oldPB=new ParameterBlock(oldSources,params);
        newPB=new ParameterBlock(newSources,params);
        checkInvalidRegion=true;
      }
      if (checkInvalidRegion) {
        fireEvent=true;
        OperationRegistry registry=nodeSupport.getRegistry();
        OperationDescriptor odesc=(OperationDescriptor)registry.getDescriptor(OperationDescriptor.class,nodeSupport.getOperationName());
        oldPB=ImageUtil.evaluateParameters(oldPB);
        newPB=ImageUtil.evaluateParameters(newPB);
        invalidRegion=(Shape)odesc.getInvalidRegion(RenderedRegistryMode.MODE_NAME,oldPB,oldHints,newPB,nodeSupport.getRenderingHints(),this);
        if (invalidRegion == null || !(theImage instanceof OpImage)) {
          theImage=null;
        }
 else {
          OpImage oldRendering=(OpImage)theImage;
          theImage=null;
          createRendering();
          if (theImage instanceof OpImage && oldRendering.getTileCache() != null && ((OpImage)theImage).getTileCache() != null) {
            OpImage newRendering=(OpImage)theImage;
            TileCache oldCache=oldRendering.getTileCache();
            TileCache newCache=newRendering.getTileCache();
            Object tileCacheMetric=newRendering.getTileCacheMetric();
            if (invalidRegion.getBounds().isEmpty()) {
              int x=oldRendering.tileXToX(oldRendering.getMinTileX());
              int y=oldRendering.tileYToY(oldRendering.getMinTileY());
              int w=oldRendering.getNumXTiles() * oldRendering.getTileWidth();
              int h=oldRendering.getNumYTiles() * oldRendering.getTileHeight();
              Rectangle tileBounds=new Rectangle(x,y,w,h);
              Rectangle imageBounds=oldRendering.getBounds();
              if (!tileBounds.equals(imageBounds)) {
                Area tmpArea=new Area(tileBounds);
                tmpArea.subtract(new Area(imageBounds));
                invalidRegion=tmpArea;
              }
            }
            if (invalidRegion.getBounds().isEmpty()) {
              Raster[] tiles=oldCache.getTiles(oldRendering);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                int tx=newRendering.XToTileX(tile.getMinX());
                int ty=newRendering.YToTileY(tile.getMinY());
                newCache.add(newRendering,tx,ty,tile,tileCacheMetric);
              }
            }
 else {
              Raster[] tiles=oldCache.getTiles(oldRendering);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                Rectangle bounds=tile.getBounds();
                if (!invalidRegion.intersects(bounds)) {
                  newCache.add(newRendering,newRendering.XToTileX(bounds.x),newRendering.YToTileY(bounds.y),tile,tileCacheMetric);
                }
              }
            }
          }
        }
      }
    }
    createRendering();
    if (fireEvent) {
      resetProperties(true);
      RenderingChangeEvent rcEvent=new RenderingChangeEvent(this,theOldImage,theImage,invalidRegion);
      eventManager.firePropertyChange(rcEvent);
      Vector sinks=getSinks();
      if (sinks != null) {
        int numSinks=sinks.size();
        for (int i=0; i < numSinks; i++) {
          Object sink=sinks.get(i);
          if (sink instanceof PropertyChangeListener) {
            ((PropertyChangeListener)sink).propertyChange(rcEvent);
          }
        }
      }
    }
  }
}

Fixed version (ground truth):
/** 
 * Implementation of <code>PropertyChangeListener</code>. <p> When invoked with an event which is an instance of <code>RenderingChangeEvent</code> or <code>CollectionChangeEvent</code> emitted by a <code>RenderedOp</code> or <code>CollectionOp</code>, respectively, the node will respond by re-rendering itself while retaining any tiles possible.  It will respond to an "InvalidRegion" event emitted by a source <code>RenderedImage</code> in a manner similar to that applied for <code>RenderingChangeEvent</code>s.
 * @see TiledImage#propertyChange
 * @since JAI 1.1
 */
public synchronized void propertyChange(PropertyChangeEvent evt){
  Object evtSrc=evt.getSource();
  Vector nodeSources=nodeSupport.getParameterBlock().getSources();
  String propName=evt.getPropertyName().toLowerCase(Locale.ENGLISH);
  if (theImage != null && ((evt instanceof PropertyChangeEventJAI && evtSrc == this && !(evt instanceof PropertySourceChangeEvent) && nodeEventNames.contains(propName)) || ((evt instanceof RenderingChangeEvent || evt instanceof CollectionChangeEvent || (evt instanceof PropertyChangeEventJAI && evtSrc instanceof RenderedImage && propName.equals("String_Node_Str"))) && nodeSources.contains(evtSrc)))) {
    PlanarImage theOldImage=theImage;
    boolean fireEvent=false;
    Shape invalidRegion=null;
    if (evtSrc == this && (propName.equals("String_Node_Str") || propName.equals("String_Node_Str"))) {
      fireEvent=true;
      theImage=null;
    }
 else     if (evt instanceof RenderingChangeEvent || (evtSrc instanceof RenderedImage && propName.equals("String_Node_Str"))) {
      fireEvent=true;
      Shape srcInvalidRegion=null;
      if (evt instanceof RenderingChangeEvent) {
        RenderingChangeEvent rcEvent=(RenderingChangeEvent)evt;
        srcInvalidRegion=rcEvent.getInvalidRegion();
        if (srcInvalidRegion == null) {
          srcInvalidRegion=((PlanarImage)rcEvent.getOldValue()).getBounds();
        }
      }
 else {
        srcInvalidRegion=(Shape)evt.getNewValue();
        if (srcInvalidRegion == null) {
          RenderedImage rSrc=(RenderedImage)evtSrc;
          srcInvalidRegion=new Rectangle(rSrc.getMinX(),rSrc.getMinY(),rSrc.getWidth(),rSrc.getHeight());
        }
      }
      if (!(theImage instanceof OpImage)) {
        theImage=null;
      }
 else {
        OpImage oldOpImage=(OpImage)theImage;
        Rectangle srcInvalidBounds=srcInvalidRegion.getBounds();
        if (srcInvalidBounds.isEmpty()) {
          int x=oldOpImage.tileXToX(oldOpImage.getMinTileX());
          int y=oldOpImage.tileYToY(oldOpImage.getMinTileY());
          int w=oldOpImage.getNumXTiles() * oldOpImage.getTileWidth();
          int h=oldOpImage.getNumYTiles() * oldOpImage.getTileHeight();
          Rectangle tileBounds=new Rectangle(x,y,w,h);
          Rectangle imageBounds=oldOpImage.getBounds();
          if (!tileBounds.equals(imageBounds)) {
            Area tmpArea=new Area(tileBounds);
            tmpArea.subtract(new Area(imageBounds));
            srcInvalidRegion=tmpArea;
            srcInvalidBounds=srcInvalidRegion.getBounds();
          }
        }
        boolean saveAllTiles=false;
        ArrayList validTiles=null;
        if (srcInvalidBounds.isEmpty()) {
          invalidRegion=srcInvalidRegion;
          saveAllTiles=true;
        }
 else {
          int idx=nodeSources.indexOf(evtSrc);
          Rectangle dstRegionBounds=oldOpImage.mapSourceRect(srcInvalidBounds,idx);
          if (dstRegionBounds == null) {
            dstRegionBounds=oldOpImage.getBounds();
          }
          Point[] indices=getTileIndices(dstRegionBounds);
          int numIndices=indices != null ? indices.length : 0;
          GeneralPath gp=null;
          for (int i=0; i < numIndices; i++) {
            if (i % 1000 == 0 && gp != null)             gp=new GeneralPath(new Area(gp));
            Rectangle dstRect=getTileRect(indices[i].x,indices[i].y);
            Rectangle srcRect=oldOpImage.mapDestRect(dstRect,idx);
            if (srcRect == null) {
              gp=null;
              break;
            }
            if (srcInvalidRegion.intersects(srcRect)) {
              if (gp == null) {
                gp=new GeneralPath(dstRect);
              }
 else {
                gp.append(dstRect,false);
              }
            }
 else {
              if (validTiles == null) {
                validTiles=new ArrayList();
              }
              validTiles.add(indices[i]);
            }
          }
          invalidRegion=(gp == null) ? null : new Area(gp);
        }
        theImage=null;
        TileCache oldCache=oldOpImage.getTileCache();
        if (oldCache != null && (saveAllTiles || validTiles != null)) {
          createRendering();
          if (theImage instanceof OpImage && ((OpImage)theImage).getTileCache() != null) {
            OpImage newOpImage=(OpImage)theImage;
            TileCache newCache=newOpImage.getTileCache();
            Object tileCacheMetric=newOpImage.getTileCacheMetric();
            if (saveAllTiles) {
              Raster[] tiles=oldCache.getTiles(oldOpImage);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                int tx=newOpImage.XToTileX(tile.getMinX());
                int ty=newOpImage.YToTileY(tile.getMinY());
                newCache.add(newOpImage,tx,ty,tile,tileCacheMetric);
              }
            }
 else {
              int numValidTiles=validTiles.size();
              for (int i=0; i < numValidTiles; i++) {
                Point tileIndex=(Point)validTiles.get(i);
                Raster tile=oldCache.getTile(oldOpImage,tileIndex.x,tileIndex.y);
                if (tile != null) {
                  newCache.add(newOpImage,tileIndex.x,tileIndex.y,tile,tileCacheMetric);
                }
              }
            }
          }
        }
      }
    }
 else {
      ParameterBlock oldPB=null;
      ParameterBlock newPB=null;
      boolean checkInvalidRegion=false;
      if (propName.equals("String_Node_Str")) {
        oldPB=(ParameterBlock)evt.getOldValue();
        newPB=(ParameterBlock)evt.getNewValue();
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        Vector params=nodeSupport.getParameterBlock().getParameters();
        oldPB=new ParameterBlock((Vector)evt.getOldValue(),params);
        newPB=new ParameterBlock((Vector)evt.getNewValue(),params);
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        oldPB=new ParameterBlock(nodeSources,(Vector)evt.getOldValue());
        newPB=new ParameterBlock(nodeSources,(Vector)evt.getNewValue());
        checkInvalidRegion=true;
      }
 else       if (propName.equals("String_Node_Str")) {
        oldPB=newPB=nodeSupport.getParameterBlock();
        checkInvalidRegion=true;
      }
 else       if (evt instanceof CollectionChangeEvent) {
        int collectionIndex=nodeSources.indexOf(evtSrc);
        Vector oldSources=(Vector)nodeSources.clone();
        Vector newSources=(Vector)nodeSources.clone();
        oldSources.set(collectionIndex,evt.getOldValue());
        newSources.set(collectionIndex,evt.getNewValue());
        Vector params=nodeSupport.getParameterBlock().getParameters();
        oldPB=new ParameterBlock(oldSources,params);
        newPB=new ParameterBlock(newSources,params);
        checkInvalidRegion=true;
      }
      if (checkInvalidRegion) {
        fireEvent=true;
        OperationRegistry registry=nodeSupport.getRegistry();
        OperationDescriptor odesc=(OperationDescriptor)registry.getDescriptor(OperationDescriptor.class,nodeSupport.getOperationName());
        oldPB=ImageUtil.evaluateParameters(oldPB);
        newPB=ImageUtil.evaluateParameters(newPB);
        invalidRegion=(Shape)odesc.getInvalidRegion(RenderedRegistryMode.MODE_NAME,oldPB,oldHints,newPB,nodeSupport.getRenderingHints(),this);
        if (invalidRegion == null || !(theImage instanceof OpImage)) {
          theImage=null;
        }
 else {
          OpImage oldRendering=(OpImage)theImage;
          theImage=null;
          createRendering();
          if (theImage instanceof OpImage && oldRendering.getTileCache() != null && ((OpImage)theImage).getTileCache() != null) {
            OpImage newRendering=(OpImage)theImage;
            TileCache oldCache=oldRendering.getTileCache();
            TileCache newCache=newRendering.getTileCache();
            Object tileCacheMetric=newRendering.getTileCacheMetric();
            if (invalidRegion.getBounds().isEmpty()) {
              int x=oldRendering.tileXToX(oldRendering.getMinTileX());
              int y=oldRendering.tileYToY(oldRendering.getMinTileY());
              int w=oldRendering.getNumXTiles() * oldRendering.getTileWidth();
              int h=oldRendering.getNumYTiles() * oldRendering.getTileHeight();
              Rectangle tileBounds=new Rectangle(x,y,w,h);
              Rectangle imageBounds=oldRendering.getBounds();
              if (!tileBounds.equals(imageBounds)) {
                Area tmpArea=new Area(tileBounds);
                tmpArea.subtract(new Area(imageBounds));
                invalidRegion=tmpArea;
              }
            }
            if (invalidRegion.getBounds().isEmpty()) {
              Raster[] tiles=oldCache.getTiles(oldRendering);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                int tx=newRendering.XToTileX(tile.getMinX());
                int ty=newRendering.YToTileY(tile.getMinY());
                newCache.add(newRendering,tx,ty,tile,tileCacheMetric);
              }
            }
 else {
              Raster[] tiles=oldCache.getTiles(oldRendering);
              int numTiles=tiles == null ? 0 : tiles.length;
              for (int i=0; i < numTiles; i++) {
                Raster tile=tiles[i];
                Rectangle bounds=tile.getBounds();
                if (!invalidRegion.intersects(bounds)) {
                  newCache.add(newRendering,newRendering.XToTileX(bounds.x),newRendering.YToTileY(bounds.y),tile,tileCacheMetric);
                }
              }
            }
          }
        }
      }
    }
    createRendering();
    if (fireEvent) {
      resetProperties(true);
      RenderingChangeEvent rcEvent=new RenderingChangeEvent(this,theOldImage,theImage,invalidRegion);
      eventManager.firePropertyChange(rcEvent);
      Vector sinks=getSinks();
      if (sinks != null) {
        int numSinks=sinks.size();
        for (int i=0; i < numSinks; i++) {
          Object sink=sinks.get(i);
          if (sink instanceof PropertyChangeListener) {
            ((PropertyChangeListener)sink).propertyChange(rcEvent);
          }
        }
      }
    }
  }
}