/*
 * Copyright 2015 Adaptris Ltd.
 * 
 * Licensed 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 com.adaptris.core.stubs;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Set;
import com.adaptris.core.AdaptrisMessage;
import com.adaptris.core.AdaptrisMessageFactory;
import com.adaptris.core.DefaultAdaptrisMessageImp;
import com.adaptris.core.MetadataElement;
import com.adaptris.util.IdGenerator;

/**
 * Stub of AdaptrisMessage for testing custom message factory.
 *
 * @author hfraser
 * @author $Author: lchan $
 */
public class DefectiveAdaptrisMessage extends DefaultAdaptrisMessageImp {

  protected DefectiveAdaptrisMessage(IdGenerator guid, AdaptrisMessageFactory amf) throws RuntimeException {
    super(guid, amf);
    setPayload(new byte[0]);
  }

  @Override
  public InputStream getInputStream() throws IOException {
    if (((DefectiveMessageFactory) getFactory()).brokenInput()) {
      return new ErroringInputStream(super.getInputStream());
    }
    return super.getInputStream();
  }

  @Override
  public OutputStream getOutputStream() throws IOException {
    if (((DefectiveMessageFactory) getFactory()).brokenOutput()) {
      return new ErroringOutputStream();
    }
    return super.getOutputStream();
  }

  @Override
  public boolean containsKey(String key) {
    return headersContainsKey(key);
  }

  /** @see AdaptrisMessage#headersContainsKey(String) */
  @Override
  public boolean headersContainsKey(String key) {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataGet()) {
      throw new RuntimeException();
    }
    return super.headersContainsKey(key);
  }

  /** @see AdaptrisMessage#addMetadata(MetadataElement) */
  @Override
  public synchronized void addMetadata(MetadataElement e) {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataSet()) {
      throw new RuntimeException();
    }
    super.addMetadata(e);
  }

  /** @see AdaptrisMessage#removeMetadata(MetadataElement) */
  @Override
  public void removeMetadata(MetadataElement element) {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataSet()) {
      throw new RuntimeException();
    }
    super.removeMetadata(element);
  }

  /** @see AdaptrisMessage#removeMessageHeader(String) */
  @Override
  public void removeMessageHeader(String key) {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataSet()) {
      throw new RuntimeException();
    }
    super.removeMessageHeader(key);
  }

  @Override
  public synchronized void clearMetadata() {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataSet()) {
      throw new RuntimeException();
    }
    super.clearMetadata();
  }

  @Override
  public Map<String, String> getMessageHeaders() {
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataGet()) {
      throw new RuntimeException();
    }
    return super.getMessageHeaders();
  }

  @Override
  public Set<MetadataElement> getMetadata() { // lgtm [java/unsynchronized-getter]
    if (((DefectiveMessageFactory) getFactory()).brokenMetadataGet()) {
      throw new RuntimeException();
    }
    return super.getMetadata();
  }


  private class ErroringOutputStream extends OutputStream {

    protected ErroringOutputStream() {
      super();
    }

    @Override
    public void write(int b) throws IOException {
      throw new IOException("Failed to write");
    }

  }

  private class ErroringInputStream extends FilterInputStream {

    protected ErroringInputStream(InputStream in) {
      super(in);
    }

    @Override
    public int read() throws IOException {
      throw new IOException("Failed to read");
    }

    @Override
    public int read(byte[] b) throws IOException {
      throw new IOException("Failed to read");
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
      throw new IOException("Failed to read");
    }

  }
}

@@ -1458,35 +1458,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -1462,25 +1462,24 @@
 getFactory()
-)
 .brokenInput
@@ -1677,35 +1677,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -1681,25 +1681,24 @@
 getFactory()
-)
 .brokenOutpu
@@ -2019,35 +2019,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -2019,33 +2019,32 @@
 if (getFactory()
-)
 .brokenMetadataG
@@ -2283,35 +2283,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -2283,33 +2283,32 @@
 if (getFactory()
-)
 .brokenMetadataS
@@ -2530,35 +2530,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -2530,33 +2530,32 @@
 if (getFactory()
-)
 .brokenMetadataS
@@ -2774,35 +2774,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -2774,33 +2774,32 @@
 if (getFactory()
-)
 .brokenMetadataS
@@ -2958,35 +2958,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -2958,33 +2958,32 @@
 if (getFactory()
-)
 .brokenMetadataS
@@ -3139,35 +3139,8 @@
 if (
-((DefectiveMessageFactory) 
 getF
@@ -3139,33 +3139,32 @@
 if (getFactory()
-)
 .brokenMetadataG
@@ -3363,35 +3363,414 @@
 if (
-((DefectiveMessageFactory) 
+getFactory().brokenMetadataGet()) %7B%0A      throw new RuntimeException();%0A    %7D%0A    return super.getMetadata();%0A  %7D%0A%0A  @Override%0A  public String getMetadataValue(String key) %7B // is case-sensitive%0A    if (getFactory().brokenMetadataGet()) %7B%0A      throw new RuntimeException();%0A    %7D%0A    return super.getMetadataValue(key);%0A  %7D%0A%0A  @Override%0A  public String getMetadataValueIgnoreKeyCase(String key) %7B%0A    if (
 getF
@@ -3777,17 +3777,16 @@
 actory()
-)
 .brokenM
@@ -3863,32 +3863,175 @@
 uper.getMetadata
+ValueIgnoreKeyCase(key);%0A  %7D%0A%0A  @Override%0A  public DefectiveMessageFactory getFactory() %7B%0A    return (DefectiveMessageFactory) super.getFactory
 ();%0A  %7D%0A%0A%0A  priv

Add defectiveness for getMetadataValue for completness.