/**
 * Copyright (c) 2016 Bosch Software Innovations GmbH.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Bosch Software Innovations GmbH - initial creation
 */
package org.eclipse.hono.util;

import org.apache.qpid.proton.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A basic filter for checking existence and correctness of mandatory message properties.
 *
 */
public class BaseMessageFilter {

    private static final Logger LOG = LoggerFactory.getLogger(BaseMessageFilter.class);

    /**
     * Checks whether a given registration message contains required standard properties.
     * <p>
     * In particular, the following conditions need to be met in order for the message to pass:
     * <ol>
     * <li>The message contains an application property {@link MessageHelper#APP_PROPERTY_DEVICE_ID}.</li>
     * <li>If the given link target contains a device id in its path, it must match the id from the property.</li>
     * </ol>
     * <p>
     * After successful verification the following properties are added to the message's <em>annotations</em>:
     * <ul>
     * <li>{@link MessageHelper#APP_PROPERTY_DEVICE_ID} - the ID of the device that reported the data.</li>
     * <li>{@link MessageHelper#APP_PROPERTY_TENANT_ID} - the ID of the tenant as indicated by the link target's second segment.</li>
     * <li>{@link MessageHelper#APP_PROPERTY_RESOURCE} - the full resource path including the endpoint, the tenant and the device ID.</li>
     * </ul>
     * 
     * @param linkTarget The resource path to check the message's properties against for consistency.
     * @param msg The AMQP 1.0 message to perform the checks on.
     * @return {@code true} if the message passes all checks.
     */
     protected static final boolean verifyStandardProperties(final ResourceIdentifier linkTarget, final Message msg) {

         final String deviceIdProperty = MessageHelper.getDeviceId(msg);

         if (deviceIdProperty == null) {
             LOG.trace("message [{}] contains no {} application property", msg.getMessageId(), MessageHelper.APP_PROPERTY_DEVICE_ID);
             return false;
         } else if (linkTarget.getResourceId() != null && !deviceIdProperty.equals(linkTarget.getResourceId())) {
             LOG.trace("message property contains invalid device ID [expected: {}, but was: {}]",
                     linkTarget.getResourceId(), deviceIdProperty);
             return false;
         } else {
             final ResourceIdentifier targetResource = ResourceIdentifier
                     .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), deviceIdProperty);
             MessageHelper.annotate(msg, targetResource);
             return true;
         }
    }
}

@@ -18,16 +18,22 @@
 (c) 2016
+, 2018
  Bosch S
@@ -784,27 +784,14 @@
 er a
- given registration
+n AMQP
  mes
@@ -856,343 +856,156 @@
   * 
-In particular, the following conditions need to be met in order for the message to pass:%0A     * %3Col%3E%0A     * %3Cli%3EThe message contains an application property %7B@link MessageHelper#APP_PROPERTY_DEVICE_ID%7D.%3C/li%3E%0A     * %3Cli%3EIf the given link target contains a device id in its path, it must match the id from the property.%3C/li%3E%0A     * %3C/ol%3E
+This method checks if the message contains a valid device identifier using%0A     * the %7B@link #hasValidDeviceId(ResourceIdentifier, Message)%7D method.
 %0A   
@@ -1890,24 +1890,1168 @@
 age msg) %7B%0A%0A
+         if (!hasValidDeviceId(linkTarget, msg)) %7B%0A             return false;%0A         %7D else %7B%0A             final ResourceIdentifier targetResource = ResourceIdentifier%0A                     .from(linkTarget.getEndpoint(), linkTarget.getTenantId(), MessageHelper.getDeviceId(msg));%0A             MessageHelper.annotate(msg, targetResource);%0A             return true;%0A         %7D%0A    %7D%0A%0A     /**%0A      * Checks if an AMQP message contains a valid device identifier.%0A      * %0A      * @param linkTarget The resource path to check the message's properties against for consistency.%0A      * @param msg The AMQP 1.0 message to perform the checks on.%0A      * @return %7B@code true%7D if the following conditions are met:%0A      *                      %3Cul%3E%0A      *                      %3Cli%3EThe message contains an application property %7B@link MessageHelper#APP_PROPERTY_DEVICE_ID%7D.%3C/li%3E%0A      *                      %3Cli%3EIf the link target contains a resource ID, it matches the ID from the property.%3C/li%3E%0A      *                      %3C/ul%3E%0A      */%0A     protected static final boolean hasValidDeviceId(final ResourceIdentifier linkTarget, final Message msg) %7B%0A%0A
          fin
@@ -3455,24 +3455,29 @@
 ace(%22message
+'s %7B%7D
  property co
@@ -3551,16 +3551,54 @@
         
+ MessageHelper.APP_PROPERTY_DEVICE_ID,
  linkTar
@@ -3699,224 +3699,545 @@
     
-final ResourceIdentifier targetResource = ResourceIdentifier%0A          
+return true;%0A         %7D%0A    %7D%0A%0A     /**%0A      * Checks if an AMQP message contains either a message ID or a correlation ID.%0A      * %0A      * @param msg The message.%0A      * @return %7B@code true%7D if the message has an ID that can be used for correlation.%0A
       
+*/%0A
      
-.from(linkTarget.getEndpoint(), linkTarget.getTenantId(), deviceIdProperty);%0A             MessageHelper.annotate(msg, targetResource);
+protected static final boolean hasCorrelationId(final Message msg) %7B%0A%0A         if (msg.getMessageId() == null && msg.getCorrelationId() == null) %7B%0A             LOG.trace(%22message has neither a message-id nor correlation-id%22);%0A             return false;%0A         %7D else %7B
 %0A   
@@ -4266,20 +4266,21 @@
 %0A         %7D%0A
+ 
     %7D%0A%7D%0A

Add methods for checking device ID and correlation ID.