From 99f57668dca924b87704583541e0e2c454a07d36 Mon Sep 17 00:00:00 2001
From: aschwinn <al.schwinn@gsi.de>
Date: Tue, 6 Jun 2017 17:15:22 +0200
Subject: [PATCH] Bug 1407 - Remove Plugin specific design validation Rules

---
 .../interface/equipment/SilecsPLC.cpp         | 11 ++--
 .../interface/equipment/SilecsRegister.cpp    | 58 +++++++++++--------
 .../interface/utility/XMLParser.cpp           | 12 ++++
 .../interface/utility/XMLParser.h             |  4 +-
 4 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
index 48e00f9..6b08a49 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
@@ -337,20 +337,19 @@ namespace Silecs
 			XMLParser xmlParser(parameterFile_,true);
 
 			// Extract general information ===========================================
-			ElementXML rootNode = xmlParser.getFirstElementFromXPath("/SILECS-Param");
+			ElementXML rootNode = xmlParser.getSingleElementFromXPath("/SILECS-Param");
 			localRelease_ = rootNode.getAttribute("silecs-version");
-
-			ElementXML ownerNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Owner");
+			ElementXML ownerNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Owner");
 			localOwner_ = ownerNode.getAttribute("user-login");
 
-			ElementXML generationNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Generation");
+			ElementXML generationNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Generation");
 			localDate_ = generationNode.getAttribute("date");
 
-			ElementXML deploymentNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/Mapping-Info/Deployment");
+			ElementXML deploymentNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/Mapping-Info/Deployment");
 			StringUtilities::fromString(localChecksum_,deploymentNode.getAttribute("checksum") );
 
 			// Extract PLC general configuration ======================================
-			ElementXML mappingNode = xmlParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping");
+			ElementXML mappingNode = xmlParser.getSingleElementFromXPath("/SILECS-Param/SILECS-Mapping");
 			//name_ = pEl->getStringAttribute("name"); already done before
 			domain_ = mappingNode.getAttribute("domain");
 			brand_ = mappingNode.getAttribute("plc-brand");
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
index 901fb36..c38f7e6 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
@@ -29,30 +29,42 @@
 namespace Silecs
 {
 
-	Register::Register(Device* theDevice,const boost::shared_ptr<ElementXML>& registerNode) : theDevice_ (theDevice)
-	{
+    Register::Register(Device* theDevice,const boost::shared_ptr<ElementXML>& registerNode) : theDevice_ (theDevice)
+    {
         name_ = registerNode->getAttribute("name");
-		format_ = whichFormatType(registerNode->getAttribute("format"));
-		StringUtilities::fromString(dimension1_,registerNode->getAttribute("array-dim1") );
-		StringUtilities::fromString(dimension2_,registerNode->getAttribute("array-dim2") );
-		StringUtilities::fromString(size_,registerNode->getAttribute("size") );
-		StringUtilities::fromString(memSize_,registerNode->getAttribute("mem-size") );
-		StringUtilities::fromString(address_,registerNode->getAttribute("address") );
-		synchro_ = Service::whichSynchroType(registerNode->getAttribute("synchro"));
-		isInitialized_ = false; //register not initialized yet (used for output registers)
-
-		// if format is string, retrieve also string-len attribute
-		if (format_ == String)
-		{
-		    StringUtilities::fromString(length_,registerNode->getAttribute("string-len") );
-		    if (DEBUG & Log::topics_) LOG(ALLOC) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", string-len: " << length_ << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_;
-		}
-		else
-		{
-		    length_ = 1;
-		    if (DEBUG & Log::topics_) LOG(ALLOC) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_;
-		}
-	}
+        length_ = 1;
+        dimension1_ = 1;
+        dimension2_ = 1;
+        std::vector< boost::shared_ptr<ElementXML> > childNodes = registerNode->childList_;
+        std::vector< boost::shared_ptr<ElementXML> >::const_iterator childIter;
+        for(childIter = childNodes.begin(); childIter != childNodes.end(); childIter++)
+        {
+            // We have to loop, since there is as well the description-element
+            format_ = whichFormatType((*childIter)->getAttribute("format"));
+            if( (*childIter)->hasAttribute("dim") )
+                StringUtilities::fromString(dimension1_,(*childIter)->getAttribute("dim") );// dim is used for 1d-arrays
+            if( (*childIter)->hasAttribute("dim1") )
+                StringUtilities::fromString(dimension1_,(*childIter)->getAttribute("dim1") );
+            if( (*childIter)->hasAttribute("dim2") )
+                StringUtilities::fromString(dimension2_,(*childIter)->getAttribute("dim2") );
+            if( (*childIter)->hasAttribute("string-length") )
+                StringUtilities::fromString(length_,(*childIter)->getAttribute("string-length") );
+        }
+        StringUtilities::fromString(size_,registerNode->getAttribute("size") );
+        StringUtilities::fromString(memSize_,registerNode->getAttribute("mem-size") );
+        StringUtilities::fromString(address_,registerNode->getAttribute("address") );
+        synchro_ = Service::whichSynchroType(registerNode->getAttribute("synchro"));
+        isInitialized_ = false; //register not initialized yet (used for output registers)
+
+        if (length_ > 1)
+        {
+            LOG(DEBUG) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", string-length: " << length_ << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_;
+        }
+        else
+        {
+            LOG(DEBUG) << "Register (create): " << name_ << ", format: " << getFormatAsString() << ", dim: " << dimension1_ << ", dim2: " << dimension2_ << ", synchro: " << getSynchroTypeAsString() << ", offset: " << address_;
+        }
+    }
 
 	Register::~Register()
 	{
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp
index 488c853..a319224 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.cpp
@@ -187,6 +187,18 @@ ElementXML XMLParser::getFirstElementFromXPath(const std::string& xpathExpressio
 	return result.get()[0];
 }
 
+ElementXML XMLParser::getSingleElementFromXPath(const std::string& xpathExpression) const
+{
+    boost::optional<boost::ptr_vector<ElementXML> > result = getElementsFromXPath_throwIfEmpty(xpathExpression);
+    if (result.get().size() > 1)
+    {
+        std::ostringstream message;
+        message << "The xpathExpression: '" << xpathExpression << "' returns more than one XML-Elements";
+        throw SilecsException(__FILE__, __LINE__, message.str().c_str());
+    }
+    return result.get()[0];
+}
+
 xmlChar* XMLParser::ConvertInput(const char *in, const char *encoding)
 {
     xmlChar *out;
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h
index b403b40..36b7849 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/XMLParser.h
@@ -109,7 +109,7 @@ class ElementXML
             }
         }
         std::ostringstream message;
-        message << "The XML Attribute " << (*attributeIter)->name_ << " was not found";
+        message << "The XML Attribute '" << attributeName << "' was not found";
         throw SilecsException(__FILE__, __LINE__, message.str().c_str());
     }
 };
@@ -142,6 +142,8 @@ class XMLParser
      */
     virtual boost::optional<boost::ptr_vector<ElementXML> > getElementsFromXPath(const std::string& xpathExpression) const;
 
+    virtual ElementXML getSingleElementFromXPath(const std::string& xpathExpression) const;
+
     virtual ElementXML getFirstElementFromXPath(const std::string& xpathExpression) const;
 
     virtual boost::ptr_vector<ElementXML> getElementsFromXPath_throwIfEmpty(const std::string& xpathExpression) const;
-- 
GitLab