<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemElement.hpp"

#include <sax/AttributeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemElement::ElemElement(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemUse(constructionContext,
			stylesheetTree,
			lineNumber,
			columnNumber,
			Constants::ELEMNAME_ELEMENT),
	m_nameAVT(0),
	m_namespaceAVT(0)
{
	// Namespace aliases are not used for xsl:element, so
	// turn them off...
	m_namespacesHandler.setProcessNamespaceAliaises(false);

	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_nameAVT = new AVT(aname,	atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_NAMESPACE))
		{
			m_namespaceAVT = new AVT(aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(processUseAttributeSets(constructionContext, aname, atts, i) || processSpaceAttr(aname, atts, i) ||
			isAttrOK(aname, atts, i, constructionContext)))
		{
			constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " has an illegal attribute: " + aname);
		}
	}

	if(0 == m_nameAVT)
	{
		constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " must have a name attribute.");
	}

}

ElemElement::~ElemElement()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_nameAVT;

	delete (AVT*)m_namespaceAVT;
#else
	delete m_nameAVT;

	delete m_namespaceAVT;
#endif
}

const XalanDOMString&
ElemElement::getElementName() const
{
	return Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING;
}

void
ElemElement::execute(StylesheetExecutionContext&		executionContext) const
{
	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameGuard(executionContext);

	XalanDOMString&		elemName = elemNameGuard.get();

	XalanNode* const	sourceNode = executionContext.getCurrentNode();

	m_nameAVT->evaluate(elemName, sourceNode, *this, executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameSpaceGuard(executionContext);

	XalanDOMString&		elemNameSpace = elemNameSpaceGuard.get();

	if (m_namespaceAVT != 0)
	{
		m_namespaceAVT->evaluate(elemNameSpace, sourceNode, *this, executionContext);
	}

	unsigned int		namespaceLen = length(elemNameSpace);

	bool				isIllegalElement = false;

	bool				hasUnresolvedPrefix = false;

	unsigned int		len = length(elemName);

	const unsigned int	indexOfNSSep = indexOf(elemName, XalanUnicode::charColon);

	const bool			haveNamespace = indexOfNSSep == len ? false : true;

	StylesheetExecutionContext::GetAndReleaseCachedString	prefixGuard(executionContext);

	XalanDOMString&		prefix = prefixGuard.get();

	if(haveNamespace == true)
	{
		if (indexOfNSSep + 1 == len ||
			isValidNCName(substring(elemName, indexOfNSSep + 1)) == false)
		{
			isIllegalElement = true;
		}
	}
	else if(len == 0 || isValidNCName(elemName) == false)
	{
		isIllegalElement = true;
	}

	if (isIllegalElement == true)
	{
		executionContext.warn("Illegal element name: \"" + elemName + "\"", this, sourceNode);

		clear(elemName);
	}
	else if (haveNamespace == true)
	{
		prefix = substring(elemName, 0, indexOfNSSep);

		const XalanDOMString* const		theNamespace =
			executionContext.getResultNamespaceForPrefix(prefix);

		if (theNamespace == 0)
		{
			const XalanDOMString* const		theNamespace =
				m_namespacesHandler.getNamespace(prefix);

			if(theNamespace == 0 && namespaceLen == 0)
			{
				executionContext.warn("Could not resolve prefix: " + prefix, this, sourceNode);

				if (m_namespaceAVT != 0)
				{
					hasUnresolvedPrefix = true;

					elemName = substring(elemName, indexOfNSSep + 1);
				}
				else
				{
					isIllegalElement = true;
				}
			}
		}
	}

	if (isIllegalElement == false)
	{
		executionContext.startElement(c_wstr(elemName));

		if(0 == m_namespaceAVT)
		{
			outputResultNamespaces(executionContext, hasUnresolvedPrefix);
		}
		else
		{
			if(namespaceLen == 0 && hasUnresolvedPrefix == true)
			{
				outputResultNamespaces(
					executionContext,
					hasUnresolvedPrefix,
					length(getParentDefaultNamespace()) == 0 ? true : false);
			}
			else
			{
				if(haveNamespace == false)
				{
					if (namespaceLen > 0)
					{
						outputResultNamespaces(executionContext, hasUnresolvedPrefix);

						executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
					}
					else
					{
						// OK, the namespace we're generating is the default namespace,
						// so let's make sure that we really need it.  If we don't,
						// we end up with another xmlns="" on the element we're
						// generating.  Although this isn't really an error, it's
						// a bit unsightly, so let's suppress it...
						const XalanDOMString& const	theParentDefaultNamespace =
							getParentDefaultNamespace();

						if (length(theParentDefaultNamespace) == 0)
						{
							// There's not default namespace in effect, so suppress any
							// default namespace in the statically-generated namespaces,
							// and don't put out the one we've dynamically generated...
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, true);
						}
						else
						{
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, false);

							executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
						}
					}
				}
				else
				{
					outputResultNamespaces(executionContext, hasUnresolvedPrefix);

					const XalanDOMString* const		theNamespace =
						executionContext.getResultNamespaceForPrefix(prefix);

					if (theNamespace == 0 ||
						equals(*theNamespace, elemNameSpace) == false)
					{
						insert(prefix, 0, DOMServices::s_XMLNamespaceWithSeparator);

						executionContext.addResultAttribute(prefix, elemNameSpace);
					}
				}
			}
		}
	}

	ElemUse::execute(executionContext);

	doExecuteChildren(executionContext, isIllegalElement);

	if (isIllegalElement == false)
	{
		executionContext.endElement(c_wstr(elemName));
	}
}

void
ElemElement::doExecuteChildren(
			StylesheetExecutionContext&		executionContext,
			bool							skipAttributeChildren) const
{
	if (skipAttributeChildren == false)
	{
		// If we should execute all children, then just call
		// executeChildren()...
		executeChildren(executionContext);
	}
	else
	{
		StylesheetExecutionContext::PushAndPopElementFrame	thePushAndPop(executionContext, this);

		for (ElemTemplateElement* node = getFirstChildElem(); node != 0; node = node->getNextSiblingElem())
		{
			if (node->getXSLToken() != Constants::ELEMNAME_ATTRIBUTE)
			{
				node->execute(executionContext);
			}
		}
	}
}

void
ElemElement::outputResultNamespaces(
			StylesheetExecutionContext&		executionContext,
			bool							hasUnresolvedPrefix,
			bool							supressDefault) const
{
	m_namespacesHandler.outputResultNamespaces(executionContext, supressDefault);

	if (supressDefault == false)
	{
		// OK, now let's check to make sure we don't have to change the default namespace...
		const XalanDOMString* const		theCurrentDefaultNamespace =
					executionContext.getResultNamespaceForPrefix(s_emptyString);

		if (theCurrentDefaultNamespace != 0)
		{
			const XalanDOMString* const		theElementDefaultNamespace =
						m_namespacesHandler.getNamespace(s_emptyString);

			if (hasUnresolvedPrefix == true || theElementDefaultNamespace == 0)
			{
				// There was no default namespace, so we have to turn the
				// current one off.
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, s_emptyString);
			}
			else if (equals(*theCurrentDefaultNamespace, *theElementDefaultNamespace) == false)
			{
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, *theElementDefaultNamespace);
			}
		}
	}
}

const XalanDOMString&
ElemElement::getParentDefaultNamespace() const
{
	const ElemTemplateElement* const	theParent =
		getParentNodeElem();

	if (theParent == 0)
	{
		return s_emptyString;
	}
	else
	{
		const XalanDOMString* const		theParentDefaultNamespace =
						theParent->getNamespacesHandler().getNamespace(s_emptyString);

		if (theParentDefaultNamespace == 0)
		{
			return s_emptyString;
		}
		else
		{
			return *theParentDefaultNamespace;
		}
	}
}
<commit_msg>Removed bogus const.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#include "ElemElement.hpp"

#include <sax/AttributeList.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "AVT.hpp"
#include "Constants.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"

ElemElement::ElemElement(
			StylesheetConstructionContext&	constructionContext,
			Stylesheet&						stylesheetTree,
			const AttributeList&			atts,
			int								lineNumber,
			int								columnNumber) :
	ElemUse(constructionContext,
			stylesheetTree,
			lineNumber,
			columnNumber,
			Constants::ELEMNAME_ELEMENT),
	m_nameAVT(0),
	m_namespaceAVT(0)
{
	// Namespace aliases are not used for xsl:element, so
	// turn them off...
	m_namespacesHandler.setProcessNamespaceAliaises(false);

	const unsigned int	nAttrs = atts.getLength();

	for(unsigned int i = 0; i < nAttrs; i++)
	{
		const XalanDOMChar*	const	aname = atts.getName(i);

		if(equals(aname, Constants::ATTRNAME_NAME))
		{
			m_nameAVT = new AVT(aname,	atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(equals(aname, Constants::ATTRNAME_NAMESPACE))
		{
			m_namespaceAVT = new AVT(aname, atts.getType(i), atts.getValue(i),
				*this, constructionContext);
		}
		else if(!(processUseAttributeSets(constructionContext, aname, atts, i) || processSpaceAttr(aname, atts, i) ||
			isAttrOK(aname, atts, i, constructionContext)))
		{
			constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " has an illegal attribute: " + aname);
		}
	}

	if(0 == m_nameAVT)
	{
		constructionContext.error(Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING + " must have a name attribute.");
	}

}

ElemElement::~ElemElement()
{
#if defined(XALAN_CANNOT_DELETE_CONST)
	delete (AVT*)m_nameAVT;

	delete (AVT*)m_namespaceAVT;
#else
	delete m_nameAVT;

	delete m_namespaceAVT;
#endif
}

const XalanDOMString&
ElemElement::getElementName() const
{
	return Constants::ELEMNAME_ELEMENT_WITH_PREFIX_STRING;
}

void
ElemElement::execute(StylesheetExecutionContext&		executionContext) const
{
	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameGuard(executionContext);

	XalanDOMString&		elemName = elemNameGuard.get();

	XalanNode* const	sourceNode = executionContext.getCurrentNode();

	m_nameAVT->evaluate(elemName, sourceNode, *this, executionContext);

	StylesheetExecutionContext::GetAndReleaseCachedString	elemNameSpaceGuard(executionContext);

	XalanDOMString&		elemNameSpace = elemNameSpaceGuard.get();

	if (m_namespaceAVT != 0)
	{
		m_namespaceAVT->evaluate(elemNameSpace, sourceNode, *this, executionContext);
	}

	unsigned int		namespaceLen = length(elemNameSpace);

	bool				isIllegalElement = false;

	bool				hasUnresolvedPrefix = false;

	unsigned int		len = length(elemName);

	const unsigned int	indexOfNSSep = indexOf(elemName, XalanUnicode::charColon);

	const bool			haveNamespace = indexOfNSSep == len ? false : true;

	StylesheetExecutionContext::GetAndReleaseCachedString	prefixGuard(executionContext);

	XalanDOMString&		prefix = prefixGuard.get();

	if(haveNamespace == true)
	{
		if (indexOfNSSep + 1 == len ||
			isValidNCName(substring(elemName, indexOfNSSep + 1)) == false)
		{
			isIllegalElement = true;
		}
	}
	else if(len == 0 || isValidNCName(elemName) == false)
	{
		isIllegalElement = true;
	}

	if (isIllegalElement == true)
	{
		executionContext.warn("Illegal element name: \"" + elemName + "\"", this, sourceNode);

		clear(elemName);
	}
	else if (haveNamespace == true)
	{
		prefix = substring(elemName, 0, indexOfNSSep);

		const XalanDOMString* const		theNamespace =
			executionContext.getResultNamespaceForPrefix(prefix);

		if (theNamespace == 0)
		{
			const XalanDOMString* const		theNamespace =
				m_namespacesHandler.getNamespace(prefix);

			if(theNamespace == 0 && namespaceLen == 0)
			{
				executionContext.warn("Could not resolve prefix: " + prefix, this, sourceNode);

				if (m_namespaceAVT != 0)
				{
					hasUnresolvedPrefix = true;

					elemName = substring(elemName, indexOfNSSep + 1);
				}
				else
				{
					isIllegalElement = true;
				}
			}
		}
	}

	if (isIllegalElement == false)
	{
		executionContext.startElement(c_wstr(elemName));

		if(0 == m_namespaceAVT)
		{
			outputResultNamespaces(executionContext, hasUnresolvedPrefix);
		}
		else
		{
			if(namespaceLen == 0 && hasUnresolvedPrefix == true)
			{
				outputResultNamespaces(
					executionContext,
					hasUnresolvedPrefix,
					length(getParentDefaultNamespace()) == 0 ? true : false);
			}
			else
			{
				if(haveNamespace == false)
				{
					if (namespaceLen > 0)
					{
						outputResultNamespaces(executionContext, hasUnresolvedPrefix);

						executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
					}
					else
					{
						// OK, the namespace we're generating is the default namespace,
						// so let's make sure that we really need it.  If we don't,
						// we end up with another xmlns="" on the element we're
						// generating.  Although this isn't really an error, it's
						// a bit unsightly, so let's suppress it...
						const XalanDOMString&	theParentDefaultNamespace =
							getParentDefaultNamespace();

						if (length(theParentDefaultNamespace) == 0)
						{
							// There's not default namespace in effect, so suppress any
							// default namespace in the statically-generated namespaces,
							// and don't put out the one we've dynamically generated...
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, true);
						}
						else
						{
							outputResultNamespaces(executionContext, hasUnresolvedPrefix, false);

							executionContext.addResultAttribute(DOMServices::s_XMLNamespace, elemNameSpace);
						}
					}
				}
				else
				{
					outputResultNamespaces(executionContext, hasUnresolvedPrefix);

					const XalanDOMString* const		theNamespace =
						executionContext.getResultNamespaceForPrefix(prefix);

					if (theNamespace == 0 ||
						equals(*theNamespace, elemNameSpace) == false)
					{
						insert(prefix, 0, DOMServices::s_XMLNamespaceWithSeparator);

						executionContext.addResultAttribute(prefix, elemNameSpace);
					}
				}
			}
		}
	}

	ElemUse::execute(executionContext);

	doExecuteChildren(executionContext, isIllegalElement);

	if (isIllegalElement == false)
	{
		executionContext.endElement(c_wstr(elemName));
	}
}

void
ElemElement::doExecuteChildren(
			StylesheetExecutionContext&		executionContext,
			bool							skipAttributeChildren) const
{
	if (skipAttributeChildren == false)
	{
		// If we should execute all children, then just call
		// executeChildren()...
		executeChildren(executionContext);
	}
	else
	{
		StylesheetExecutionContext::PushAndPopElementFrame	thePushAndPop(executionContext, this);

		for (ElemTemplateElement* node = getFirstChildElem(); node != 0; node = node->getNextSiblingElem())
		{
			if (node->getXSLToken() != Constants::ELEMNAME_ATTRIBUTE)
			{
				node->execute(executionContext);
			}
		}
	}
}

void
ElemElement::outputResultNamespaces(
			StylesheetExecutionContext&		executionContext,
			bool							hasUnresolvedPrefix,
			bool							supressDefault) const
{
	m_namespacesHandler.outputResultNamespaces(executionContext, supressDefault);

	if (supressDefault == false)
	{
		// OK, now let's check to make sure we don't have to change the default namespace...
		const XalanDOMString* const		theCurrentDefaultNamespace =
					executionContext.getResultNamespaceForPrefix(s_emptyString);

		if (theCurrentDefaultNamespace != 0)
		{
			const XalanDOMString* const		theElementDefaultNamespace =
						m_namespacesHandler.getNamespace(s_emptyString);

			if (hasUnresolvedPrefix == true || theElementDefaultNamespace == 0)
			{
				// There was no default namespace, so we have to turn the
				// current one off.
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, s_emptyString);
			}
			else if (equals(*theCurrentDefaultNamespace, *theElementDefaultNamespace) == false)
			{
				executionContext.addResultAttribute(DOMServices::s_XMLNamespace, *theElementDefaultNamespace);
			}
		}
	}
}

const XalanDOMString&
ElemElement::getParentDefaultNamespace() const
{
	const ElemTemplateElement* const	theParent =
		getParentNodeElem();

	if (theParent == 0)
	{
		return s_emptyString;
	}
	else
	{
		const XalanDOMString* const		theParentDefaultNamespace =
						theParent->getNamespacesHandler().getNamespace(s_emptyString);

		if (theParentDefaultNamespace == 0)
		{
			return s_emptyString;
		}
		else
		{
			return *theParentDefaultNamespace;
		}
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ContentHelper.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-23 09:47:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBA_CONTENTHELPER_HXX
#define DBA_CONTENTHELPER_HXX

#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENT_HPP_
#include <com/sun/star/ucb/XContent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCOMMANDPROCESSOR_HPP_
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTIESCHANGENOTIFIER_HPP_
#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HPP_
#include <com/sun/star/beans/XPropertyContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_
#include <com/sun/star/embed/XStorage.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XEMBEDDEDOBJECT_HPP_
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE9_HXX_
#include <cppuhelper/compbase9.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_
#include <com/sun/star/beans/Property.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_
#include <com/sun/star/sdbcx/XRename.hpp>
#endif
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

namespace dbaccess
{
    class ODatabaseModelImpl;
    struct ContentProperties
    {
        ::rtl::OUString aTitle;         // Title
        ::rtl::OUString aContentType;   // ContentType
        sal_Bool        bIsDocument;    // IsDocument
        sal_Bool        bIsFolder;      // IsFolder
        sal_Bool        bAsTemplate;    // AsTemplate
        ::rtl::OUString sPersistentName;// persistent name of the document

        // @@@ Add other properties supported by your content.

        ContentProperties()
        : bIsDocument( sal_True ), bIsFolder( sal_False ), bAsTemplate( sal_False ) {}
    };

    class OContentHelper_Impl
    {
    public:
        OContentHelper_Impl();
        virtual ~OContentHelper_Impl();

        ContentProperties   m_aProps;
        ODatabaseModelImpl* m_pDataSource; // this will stay alive as long as the content exists
    };

    typedef ::boost::shared_ptr<OContentHelper_Impl> TContentPtr;

    typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<  ::rtl::OUString,
                                                            ::comphelper::UStringHash,
                                                            ::comphelper::UStringEqual
                                                        > PropertyChangeListenerContainer;
    typedef ::comphelper::OMutexAndBroadcastHelper  OContentHelper_MBASE;
    typedef ::cppu::WeakComponentImplHelper9    <   ::com::sun::star::ucb::XContent
                                                ,   ::com::sun::star::ucb::XCommandProcessor
                                                ,   ::com::sun::star::lang::XServiceInfo
                                                ,   ::com::sun::star::beans::XPropertiesChangeNotifier
                                                ,   ::com::sun::star::beans::XPropertyContainer
                                                ,   ::com::sun::star::lang::XInitialization
                                                ,   ::com::sun::star::lang::XUnoTunnel
                                                ,   ::com::sun::star::container::XChild
                                                ,   ::com::sun::star::sdbcx::XRename
                                                >   OContentHelper_COMPBASE;

    class OContentHelper :   public OContentHelper_MBASE
                            ,public OContentHelper_COMPBASE
    {
        ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >
            setPropertyValues( const ::com::sun::star::uno::Sequence<
                                ::com::sun::star::beans::PropertyValue >& rValues,
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::ucb::XCommandEnvironment >& xEnv );
        com::sun::star::uno::Sequence< com::sun::star::beans::Property >
            getProperties( const com::sun::star::uno::Reference<
                            com::sun::star::ucb::XCommandEnvironment > & xEnv );

    protected:
        ::cppu::OInterfaceContainerHelper   m_aContentListeners;
        PropertyChangeListenerContainer     m_aPropertyChangeListeners;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >               m_xParentContainer;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >    m_xORB;
        TContentPtr                     m_pImpl;
        sal_uInt32                      m_nCommandId;

        // helper
        virtual void SAL_CALL disposing();

        virtual void notifyDataSourceModified();

        /**
        * This method can be used to propagate changes of property values.
        *
        * @param evt is a sequence of property change events.
        */
        void notifyPropertiesChange( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent >& evt ) const;
    public:

        OContentHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB
                        ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&   _xParentContainer
                        ,const TContentPtr& _pImpl
                    );

        // com::sun::star::lang::XTypeProvider
        DECLARE_IMPLEMENTATION_ID( );
        // ::com::sun::star::lang::XServiceInfo
        DECLARE_SERVICE_INFO();

        // XContent
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentIdentifier > SAL_CALL getIdentifier(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual ::rtl::OUString SAL_CALL getContentType(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL addContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removeContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;

        // XCommandProcessor
        virtual sal_Int32 SAL_CALL createCommandIdentifier(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL abort( sal_Int32 CommandId ) throw (::com::sun::star::uno::RuntimeException) ;

        // XPropertiesChangeNotifier
        virtual void SAL_CALL addPropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removePropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;

        // XPropertyContainer
        virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException) ;

        // XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // com::sun::star::lang::XUnoTunnel
        virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

        // ::com::sun::star::container::XChild
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);

        // XRename
        virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);

        // helper
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage> getStorage() const;

        inline const ContentProperties& getContentProperties() const { return m_pImpl->m_aProps; }
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow >
            getPropertyValues( const ::com::sun::star::uno::Sequence<
                            ::com::sun::star::beans::Property >& rProperties );

        inline TContentPtr getImpl() const { return m_pImpl; }
    };

//........................................................................
}   // namespace dbaccess
//........................................................................
#endif // DBA_CONTENTHELPER_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.96); FILE MERGED 2005/09/05 17:32:25 rt 1.5.96.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ContentHelper.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 13:32:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef DBA_CONTENTHELPER_HXX
#define DBA_CONTENTHELPER_HXX

#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENT_HPP_
#include <com/sun/star/ucb/XContent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCOMMANDPROCESSOR_HPP_
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTIESCHANGENOTIFIER_HPP_
#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HPP_
#include <com/sun/star/beans/XPropertyContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_
#include <com/sun/star/embed/XStorage.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XEMBEDDEDOBJECT_HPP_
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE9_HXX_
#include <cppuhelper/compbase9.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_
#include <com/sun/star/beans/Property.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_
#include <com/sun/star/sdbcx/XRename.hpp>
#endif
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

namespace dbaccess
{
    class ODatabaseModelImpl;
    struct ContentProperties
    {
        ::rtl::OUString aTitle;         // Title
        ::rtl::OUString aContentType;   // ContentType
        sal_Bool        bIsDocument;    // IsDocument
        sal_Bool        bIsFolder;      // IsFolder
        sal_Bool        bAsTemplate;    // AsTemplate
        ::rtl::OUString sPersistentName;// persistent name of the document

        // @@@ Add other properties supported by your content.

        ContentProperties()
        : bIsDocument( sal_True ), bIsFolder( sal_False ), bAsTemplate( sal_False ) {}
    };

    class OContentHelper_Impl
    {
    public:
        OContentHelper_Impl();
        virtual ~OContentHelper_Impl();

        ContentProperties   m_aProps;
        ODatabaseModelImpl* m_pDataSource; // this will stay alive as long as the content exists
    };

    typedef ::boost::shared_ptr<OContentHelper_Impl> TContentPtr;

    typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<  ::rtl::OUString,
                                                            ::comphelper::UStringHash,
                                                            ::comphelper::UStringEqual
                                                        > PropertyChangeListenerContainer;
    typedef ::comphelper::OMutexAndBroadcastHelper  OContentHelper_MBASE;
    typedef ::cppu::WeakComponentImplHelper9    <   ::com::sun::star::ucb::XContent
                                                ,   ::com::sun::star::ucb::XCommandProcessor
                                                ,   ::com::sun::star::lang::XServiceInfo
                                                ,   ::com::sun::star::beans::XPropertiesChangeNotifier
                                                ,   ::com::sun::star::beans::XPropertyContainer
                                                ,   ::com::sun::star::lang::XInitialization
                                                ,   ::com::sun::star::lang::XUnoTunnel
                                                ,   ::com::sun::star::container::XChild
                                                ,   ::com::sun::star::sdbcx::XRename
                                                >   OContentHelper_COMPBASE;

    class OContentHelper :   public OContentHelper_MBASE
                            ,public OContentHelper_COMPBASE
    {
        ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >
            setPropertyValues( const ::com::sun::star::uno::Sequence<
                                ::com::sun::star::beans::PropertyValue >& rValues,
                            const ::com::sun::star::uno::Reference<
                                ::com::sun::star::ucb::XCommandEnvironment >& xEnv );
        com::sun::star::uno::Sequence< com::sun::star::beans::Property >
            getProperties( const com::sun::star::uno::Reference<
                            com::sun::star::ucb::XCommandEnvironment > & xEnv );

    protected:
        ::cppu::OInterfaceContainerHelper   m_aContentListeners;
        PropertyChangeListenerContainer     m_aPropertyChangeListeners;
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >               m_xParentContainer;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >    m_xORB;
        TContentPtr                     m_pImpl;
        sal_uInt32                      m_nCommandId;

        // helper
        virtual void SAL_CALL disposing();

        virtual void notifyDataSourceModified();

        /**
        * This method can be used to propagate changes of property values.
        *
        * @param evt is a sequence of property change events.
        */
        void notifyPropertiesChange( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent >& evt ) const;
    public:

        OContentHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB
                        ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&   _xParentContainer
                        ,const TContentPtr& _pImpl
                    );

        // com::sun::star::lang::XTypeProvider
        DECLARE_IMPLEMENTATION_ID( );
        // ::com::sun::star::lang::XServiceInfo
        DECLARE_SERVICE_INFO();

        // XContent
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentIdentifier > SAL_CALL getIdentifier(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual ::rtl::OUString SAL_CALL getContentType(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL addContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removeContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;

        // XCommandProcessor
        virtual sal_Int32 SAL_CALL createCommandIdentifier(  ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL abort( sal_Int32 CommandId ) throw (::com::sun::star::uno::RuntimeException) ;

        // XPropertiesChangeNotifier
        virtual void SAL_CALL addPropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removePropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ;

        // XPropertyContainer
        virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ;
        virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException) ;

        // XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // com::sun::star::lang::XUnoTunnel
        virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

        // ::com::sun::star::container::XChild
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);

        // XRename
        virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);

        // helper
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage> getStorage() const;

        inline const ContentProperties& getContentProperties() const { return m_pImpl->m_aProps; }
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow >
            getPropertyValues( const ::com::sun::star::uno::Sequence<
                            ::com::sun::star::beans::Property >& rProperties );

        inline TContentPtr getImpl() const { return m_pImpl; }
    };

//........................................................................
}   // namespace dbaccess
//........................................................................
#endif // DBA_CONTENTHELPER_HXX
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// 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.

#define OSVR_HAVE_BOOST

// Internal Includes
#include "../ConfigParams.h"
#include "../ConfigurationParser.h"
#include "../MakeHDKTrackingSystem.h"
#include "../TrackedBodyTarget.h"
#include "CSVCellGroup.h"
#include <CameraParameters.h>
#include <EdgeHoleBasedLedExtractor.h>
#include <UndistortMeasurements.h>
#include <osvr/Util/CSV.h>
#include <osvr/Util/MiniArgsHandling.h>
#include <osvr/Util/TimeValue.h>

// Library/third-party includes
#include <boost/algorithm/string/predicate.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

// Standard includes
#include <chrono>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>

namespace osvr {
namespace vbtracker {

    namespace {
        struct BodyIdOrdering {
            bool operator()(BodyId const &lhs, BodyId const &rhs) const {
                return lhs.value() < rhs.value();
            }
        };
    } // namespace
    class TrackerOfflineProcessing {
      public:
        TrackerOfflineProcessing(ConfigParams const &initialParams)
            : camParamsDistorted_(osvr::vbtracker::getHDKCameraParameters()),
              camParams_(camParamsDistorted_.createUndistortedVariant()),
              params_(initialParams), extractor_(initialParams.extractParams) {
            params_.performingOptimization = true;
            params_.silent = true;
            params_.debug = false;

            params_.offsetToCentroid = false;
            params_.includeRearPanel = false;
            params_.imu.path = "";
            params_.imu.useOrientation = false;

            system_ = makeHDKTrackingSystem(params_);
            body_ = &(system_->getBody(bodyIdOfInterest));
            target_ = body_->getTarget(targetIdOfInterest);
        }

        void processFrame(cv::Mat const &frame);

        void outputCSV(std::ostream &os) { csv_.output(os); }

      private:
        /// Substitute for performInitialImageProcessing that lets us get more
        /// of the innards: sets rawMeasurements_, undistortedMeasurements_, and
        /// leaves useful state in extractor_.
        ImageOutputDataPtr imageProc(cv::Mat const &frame);
        void logRow();

        /// @name Constants
        /// @{
        const int fps_ = 100;
        const std::chrono::microseconds frameTime_ =
            std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::seconds(1)) /
            fps_;

        const BodyId bodyIdOfInterest = BodyId(0);
        const TargetId targetIdOfInterest = TargetId(0);
        /// @}

        const CameraParameters camParamsDistorted_;
        const CameraParameters camParams_;
        ConfigParams params_;
        EdgeHoleBasedLedExtractor extractor_;
        std::unique_ptr<TrackingSystem> system_;
        TrackedBody *body_ = nullptr;
        TrackedBodyTarget *target_ = nullptr;
        util::time::TimeValue currentTime_ = {};
        LedMeasurementVec rawMeasurements_;
        LedMeasurementVec undistortedMeasurements_;
        util::CSV csv_;
        std::size_t frame_ = 0;
    };

    void TrackerOfflineProcessing::processFrame(cv::Mat const &frame) {
        std::cout << "Processing frame " << frame_ << "\n";
        /// Advance the clock
        currentTime_.microseconds += frameTime_.count();
        osvrTimeValueNormalize(&currentTime_);

        /// Image processing.
        auto imageData = imageProc(frame);

        /// Hand off the image processing results
        auto indices = system_->updateBodiesFromVideoData(std::move(imageData));
        logRow();
        frame_++;
    }

    ImageOutputDataPtr
    TrackerOfflineProcessing::imageProc(cv::Mat const &frame) {
        ImageOutputDataPtr ret(new ImageProcessingOutput);
        ret->tv = currentTime_;
        ret->frame = frame;
        cv::Mat gray;
        cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
        ret->frameGray = gray;
        ret->camParams = camParams_; // undistorted!
        rawMeasurements_ = extractor_(gray, params_.blobParams, false);
        undistortedMeasurements_ =
            undistortLeds(rawMeasurements_, camParamsDistorted_);
        ret->ledMeasurements = undistortedMeasurements_;
        return ret;
    }

    void TrackerOfflineProcessing::logRow() {
        using namespace osvr::util;
        auto row = csv_.row();
        row << cellGroup(currentTime_)
            << cell("hasPose", body_->hasPoseEstimate() ? "TRUE" : "FALSE");
        if (body_->hasPoseEstimate()) {
            Eigen::Quaterniond quat = body_->getState().getQuaternion();
            Eigen::Vector3d xlate = body_->getState().position();
            row << cellGroup(xlate) << cellGroup(quat);
        }
        row << cell("Measurements", rawMeasurements_.size());

        std::size_t numArea = 0;
        std::size_t numCenterPointValue = 0;
        std::size_t numCircularity = 0;
        std::size_t numConvexity = 0;
        for (auto &reject : extractor_.getRejectList()) {
            RejectReason reason = std::get<1>(reject);

            switch (reason) {
            case RejectReason::Area:
                numArea++;
                break;
            case RejectReason::CenterPointValue:
                numCenterPointValue++;
                break;
            case RejectReason::Circularity:
                numCircularity++;
                break;
            case RejectReason::Convexity:
                numConvexity++;
                break;
            default:
                break;
            }
        }
        row << cell("Rejects.Area", numArea)
            << cell("Rejects.CenterPointValue", numCenterPointValue)
            << cell("Rejects.Circularity", numCircularity)
            << cell("Rejects.Convexity", numConvexity);
    }

    void processAVI(std::string const &fn, TrackerOfflineProcessing &app) {
        cv::VideoCapture capture;
        capture.open(fn);
        if (!capture.isOpened()) {
            std::cerr << "Could not open video file " << fn << std::endl;
            return;
        }
        cv::Mat frame;
        capture >> frame;
        while (capture.read(frame)) {
            app.processFrame(frame);
        }
    }

} // namespace vbtracker
} // namespace osvr

using namespace osvr::util::args;
int main(int argc, char *argv[]) {

    bool gotParams = false;
    osvr::vbtracker::ConfigParams params;
    std::string videoName;
    auto args = makeArgList(argc, argv);
    try {
        /// parse json file arguments.
        auto numJson = handle_arg(args, [&](std::string const &arg) {
            if (!boost::iends_with(arg, ".json")) {
                return false;
            }
            std::ifstream configFile(arg);
            if (!configFile) {
                std::cerr << "Tried to load " << arg
                          << " as a config file but could not open it!"
                          << std::endl;
                throw std::invalid_argument(
                    "Could not open json config file passed");
            }
            Json::Value root;
            Json::Reader reader;
            if (!reader.parse(configFile, root)) {
                std::cerr << "Could not parse " << arg << " as JSON! "
                          << reader.getFormattedErrorMessages() << std::endl;
                throw std::runtime_error(
                    "Config file could not be parsed as JSON!");
            }
            params = osvr::vbtracker::parseConfigParams(root);
            return true;
        });
        if (numJson > 1) {
            std::cerr << "At most one .json config file passed to this app!"
                      << std::endl;
            return -1;
        }

        /// Get video filename
        auto numVideoNames = handle_arg(args, [&](std::string const &arg) {
            auto ret = boost::iends_with(arg, ".avi");
            if (ret) {
                videoName = arg;
            }
            return ret;
        });
        if (numVideoNames != 1) {
            std::cerr << "Must pass exactly one video filename to this app!"
                      << std::endl;
            return -1;
        }

        if (!args.empty()) {
            std::cerr
                << "Unrecognized arguments left after parsing command line!"
                << std::endl;
            return -1;
        }
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
        return -1;
    }

    osvr::vbtracker::TrackerOfflineProcessing app(params);
    osvr::vbtracker::processAVI(videoName, app);

    {
        std::cout << "Writing output data" << std::endl;
        std::ofstream of("outdata.csv");
        app.outputCSV(of);
    }
    return 0;
}<commit_msg>Don't print every frame.<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// 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.

#define OSVR_HAVE_BOOST

// Internal Includes
#include "../ConfigParams.h"
#include "../ConfigurationParser.h"
#include "../MakeHDKTrackingSystem.h"
#include "../TrackedBodyTarget.h"
#include "CSVCellGroup.h"
#include <CameraParameters.h>
#include <EdgeHoleBasedLedExtractor.h>
#include <UndistortMeasurements.h>
#include <osvr/Util/CSV.h>
#include <osvr/Util/MiniArgsHandling.h>
#include <osvr/Util/TimeValue.h>

// Library/third-party includes
#include <boost/algorithm/string/predicate.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

// Standard includes
#include <chrono>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>

namespace osvr {
namespace vbtracker {

    namespace {
        struct BodyIdOrdering {
            bool operator()(BodyId const &lhs, BodyId const &rhs) const {
                return lhs.value() < rhs.value();
            }
        };
    } // namespace
    class TrackerOfflineProcessing {
      public:
        TrackerOfflineProcessing(ConfigParams const &initialParams)
            : camParamsDistorted_(osvr::vbtracker::getHDKCameraParameters()),
              camParams_(camParamsDistorted_.createUndistortedVariant()),
              params_(initialParams), extractor_(initialParams.extractParams) {
            params_.performingOptimization = true;
            params_.silent = true;
            params_.debug = false;

            params_.offsetToCentroid = false;
            params_.includeRearPanel = false;
            params_.imu.path = "";
            params_.imu.useOrientation = false;

            system_ = makeHDKTrackingSystem(params_);
            body_ = &(system_->getBody(bodyIdOfInterest));
            target_ = body_->getTarget(targetIdOfInterest);
        }

        void processFrame(cv::Mat const &frame);

        void outputCSV(std::ostream &os) { csv_.output(os); }

      private:
        /// Substitute for performInitialImageProcessing that lets us get more
        /// of the innards: sets rawMeasurements_, undistortedMeasurements_, and
        /// leaves useful state in extractor_.
        ImageOutputDataPtr imageProc(cv::Mat const &frame);
        void logRow();

        /// @name Constants
        /// @{
        const int fps_ = 100;
        const std::chrono::microseconds frameTime_ =
            std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::seconds(1)) /
            fps_;

        const BodyId bodyIdOfInterest = BodyId(0);
        const TargetId targetIdOfInterest = TargetId(0);
        /// @}

        const CameraParameters camParamsDistorted_;
        const CameraParameters camParams_;
        ConfigParams params_;
        EdgeHoleBasedLedExtractor extractor_;
        std::unique_ptr<TrackingSystem> system_;
        TrackedBody *body_ = nullptr;
        TrackedBodyTarget *target_ = nullptr;
        util::time::TimeValue currentTime_ = {};
        LedMeasurementVec rawMeasurements_;
        LedMeasurementVec undistortedMeasurements_;
        util::CSV csv_;
        std::size_t frame_ = 0;
    };

    void TrackerOfflineProcessing::processFrame(cv::Mat const &frame) {
        if ((frame_ % 100) == 0) {
            std::cout << "Processing frame " << frame_ << std::endl;
        }
        /// Advance the clock
        currentTime_.microseconds += frameTime_.count();
        osvrTimeValueNormalize(&currentTime_);

        /// Image processing.
        auto imageData = imageProc(frame);

        /// Hand off the image processing results
        auto indices = system_->updateBodiesFromVideoData(std::move(imageData));
        logRow();
        frame_++;
    }

    ImageOutputDataPtr
    TrackerOfflineProcessing::imageProc(cv::Mat const &frame) {
        ImageOutputDataPtr ret(new ImageProcessingOutput);
        ret->tv = currentTime_;
        ret->frame = frame;
        cv::Mat gray;
        cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
        ret->frameGray = gray;
        ret->camParams = camParams_; // undistorted!
        rawMeasurements_ = extractor_(gray, params_.blobParams, false);
        undistortedMeasurements_ =
            undistortLeds(rawMeasurements_, camParamsDistorted_);
        ret->ledMeasurements = undistortedMeasurements_;
        return ret;
    }

    void TrackerOfflineProcessing::logRow() {
        using namespace osvr::util;
        auto row = csv_.row();
        row << cellGroup(currentTime_)
            << cell("hasPose", body_->hasPoseEstimate() ? "TRUE" : "FALSE");
        if (body_->hasPoseEstimate()) {
            Eigen::Quaterniond quat = body_->getState().getQuaternion();
            Eigen::Vector3d xlate = body_->getState().position();
            row << cellGroup(xlate) << cellGroup(quat);
        }
        row << cell("Measurements", rawMeasurements_.size());

        std::size_t numArea = 0;
        std::size_t numCenterPointValue = 0;
        std::size_t numCircularity = 0;
        std::size_t numConvexity = 0;
        for (auto &reject : extractor_.getRejectList()) {
            RejectReason reason = std::get<1>(reject);

            switch (reason) {
            case RejectReason::Area:
                numArea++;
                break;
            case RejectReason::CenterPointValue:
                numCenterPointValue++;
                break;
            case RejectReason::Circularity:
                numCircularity++;
                break;
            case RejectReason::Convexity:
                numConvexity++;
                break;
            default:
                break;
            }
        }
        row << cell("Rejects.Area", numArea)
            << cell("Rejects.CenterPointValue", numCenterPointValue)
            << cell("Rejects.Circularity", numCircularity)
            << cell("Rejects.Convexity", numConvexity);
    }

    void processAVI(std::string const &fn, TrackerOfflineProcessing &app) {
        cv::VideoCapture capture;
        capture.open(fn);
        if (!capture.isOpened()) {
            std::cerr << "Could not open video file " << fn << std::endl;
            return;
        }
        cv::Mat frame;
        capture >> frame;
        while (capture.read(frame)) {
            app.processFrame(frame);
        }
    }

} // namespace vbtracker
} // namespace osvr

using namespace osvr::util::args;
int main(int argc, char *argv[]) {

    bool gotParams = false;
    osvr::vbtracker::ConfigParams params;
    std::string videoName;
    auto args = makeArgList(argc, argv);
    try {
        /// parse json file arguments.
        auto numJson = handle_arg(args, [&](std::string const &arg) {
            if (!boost::iends_with(arg, ".json")) {
                return false;
            }
            std::ifstream configFile(arg);
            if (!configFile) {
                std::cerr << "Tried to load " << arg
                          << " as a config file but could not open it!"
                          << std::endl;
                throw std::invalid_argument(
                    "Could not open json config file passed");
            }
            Json::Value root;
            Json::Reader reader;
            if (!reader.parse(configFile, root)) {
                std::cerr << "Could not parse " << arg << " as JSON! "
                          << reader.getFormattedErrorMessages() << std::endl;
                throw std::runtime_error(
                    "Config file could not be parsed as JSON!");
            }
            params = osvr::vbtracker::parseConfigParams(root);
            return true;
        });
        if (numJson > 1) {
            std::cerr << "At most one .json config file passed to this app!"
                      << std::endl;
            return -1;
        }

        /// Get video filename
        auto numVideoNames = handle_arg(args, [&](std::string const &arg) {
            auto ret = boost::iends_with(arg, ".avi");
            if (ret) {
                videoName = arg;
            }
            return ret;
        });
        if (numVideoNames != 1) {
            std::cerr << "Must pass exactly one video filename to this app!"
                      << std::endl;
            return -1;
        }

        if (!args.empty()) {
            std::cerr
                << "Unrecognized arguments left after parsing command line!"
                << std::endl;
            return -1;
        }
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
        return -1;
    }

    osvr::vbtracker::TrackerOfflineProcessing app(params);
    osvr::vbtracker::processAVI(videoName, app);

    {
        std::cout << "Writing output data" << std::endl;
        std::ofstream of("outdata.csv");
        app.outputCSV(of);
    }
    return 0;
}<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#define GSL_THROW_ON_CONTRACT_VIOLATION
#define NO_INFO 1
#include <common.cxx>
#include <iostream>
#include <kernel/memmap.hpp>

CASE ("Using the fixed memory range class")
{
    GIVEN ("A fixed memory range over raw sequence of bytes")
    {
      // A dynamically allocated "raw pool" of bytes
      // @note : In the kernel memory map these would be physical ranges
      char* seq = const_cast<char*>("Spans provide a safer way to access memory");
      Fixed_memory_range range(reinterpret_cast<uintptr_t>(seq + 16),
                                 reinterpret_cast<uintptr_t>(seq + 21), "Demo range",
                               "A range inside a local pool");

      EXPECT(range.size() == 21-16);
      EXPECT(std::string(range.name()) == std::string("Demo range"));

      THEN("You can iterate safely over that range, and not out of bounds"){
        for (auto i : range)
          EXPECT(i);

        auto i = range.begin();
        for (; i != range.end(); i++)
          EXPECT(*i);

        EXPECT_THROWS(++i);
        EXPECT_THROWS(i++);

      }

      AND_THEN("You can check if any address is within that range") {

        EXPECT(not range.in_range(1));
        EXPECT(not range.in_range((uintptr_t)seq));
        EXPECT(range.in_range((uintptr_t)seq + 16));
        EXPECT(range.in_range((uintptr_t)seq + 21));
        EXPECT(not range.in_range((uintptr_t)seq + 22));
      }

      AND_THEN("You can resize that range (but you should let the memory map do that)")
        {
          auto sz = range.size();
          range.resize(range.size() + 100);
          EXPECT(range.size() == sz + 100);
          range.resize(range.size() + 10000);
          EXPECT(range.size() == sz + 10100);
        }
    }
}

CASE ("Using the kernel memory map") {

  GIVEN ("An instance of the memory map with a named range")
    {
      Memory_map map{};
      EXPECT(map.size() == 0);
      uintptr_t init_key = 0xff;
      uintptr_t init_end = 0xffff;
      auto init_size = init_end - init_key;
      map.assign_range({init_key, init_end, "Initial", "The first range"});
      EXPECT(map.size() == 1);
      EXPECT(not map.empty());
      auto& range_init = map.at(init_key);
      EXPECT(range_init.in_use() == range_init.size());

      THEN("A copy of that range is identical")
        {
          auto& range = map.at(init_key);
          Fixed_memory_range my_copy = range;
          EXPECT(range.size() == my_copy.size());
          EXPECT(range.in_use() == my_copy.in_use());
          EXPECT(range.addr_start() == my_copy.addr_start());
          EXPECT(range.addr_end() == my_copy.addr_end());
          EXPECT(range.to_string() == my_copy.to_string());
        }

      AND_THEN("The range object can be moved")
        {
          auto& range = map.at(init_key);
          Fixed_memory_range my_copy = std::move(range);
          EXPECT(range.size() == my_copy.size());
          EXPECT(range.in_use() == my_copy.in_use());
          EXPECT(range.addr_start() == my_copy.addr_start());
          EXPECT(range.addr_end() == my_copy.addr_end());
          EXPECT(range.to_string() == my_copy.to_string());
        }

      AND_THEN("You can fetch that range using start address as key")
        {
          auto& range = map.at(init_key);
          EXPECT(range.size() == init_end - init_key);

        }

      AND_THEN("You can ask the memory map if an address is in that range")
        {
          EXPECT(map.in_range(0xff1) == init_key);
          EXPECT(map.at(map.in_range(0xfff)).addr_start() == init_key);
          EXPECT(map.at(map.in_range(0xfffa)).addr_start() == init_key);
          EXPECT_NOT(map.in_range(2));
          EXPECT_NOT(map.in_range(0xf));
          EXPECT_NOT(map.in_range(0xffffff));

          // 0 is not a valid key (spans can start at address 0)
          EXPECT_THROWS(map.at(map.in_range(0)));
        }

      AND_THEN("You can increase the size of that range since nothing is above")
        {
          EXPECT(map.resize(init_key, init_size + 1) == init_size + 1);
          EXPECT(map.resize(init_key, init_size + 100) == init_size + 100);
        }

      AND_THEN("You can't downsize that range, since in_use is all of it by default")
        {
          EXPECT_THROWS(map.resize(init_key, init_size));
          EXPECT_THROWS(map.resize(init_key, 5));
        }

      AND_WHEN("You provide a custom in_use delegate you can downsize")
        {

          auto key = map.at(init_key).addr_end() + 1;
          map.assign_range({key, key + 1000, "Resizable",
                "A resizable range", []()->ptrdiff_t{ return 4; }});

          auto res = map.resize(key, 5);
          EXPECT(res == 5);
          EXPECT(map.at(key).size() == res);
          EXPECT(map.resize(key, 100) == 100);
          EXPECT(map.resize(key, 200) == 200);
          EXPECT(map.resize(key, 20000) == 20000);

          THEN("You still can't downsize to less than what it currently uses")
            {

              EXPECT_THROWS(map.resize(key, 3));

              AND_THEN("If you assign a range above it, you can't increase it further")
                {

                  auto& last_range = map.at(key);
                  auto key2 = last_range.addr_end() + 1;
                  map.assign_range({key2, key2 + 1000, "Above Resizable",
                    "A barrier for resizable"});

                  EXPECT_THROWS(map.resize(key, last_range.size() + 1));
                  EXPECT_THROWS(map.resize(key, last_range.size() + 100));
                }

            }
        }

      AND_THEN("You can't insert an overlapping range")
        {
          EXPECT_THROWS(map.assign_range({0x1, 0xfff, "Range 2", "Overlapping beginning of Range 1"}));
          EXPECT_THROWS(map.assign_range({0xfff, 0xfffff, "Range 3", "Overlapping end of Range 1"}));
        }

      AND_THEN("You can't insert an embedded  range")
        {
          EXPECT_THROWS(map.assign_range({0xfff, 0xfffa, "Range 4", "Embedded in range 1"}));
        }

      AND_WHEN("You've inserted several ranges you can iterate over them")
        {

          uintptr_t start = 0x10000;
          const size_t size = 100;
          const size_t count = 20;

          for (auto i = start; i < start + count * size; i += size + 1) {
            Fixed_memory_range rng = {i , i + size,
                                      "demo",
                                      std::string("The ") + std::to_string(i) + std::string("'th range")};
            map.assign_range(std::move(rng));
          }

          EXPECT(map.size() == count + 1);

          for (auto i : map) {
            if (std::string(i.second.name()) == "demo") {
              EXPECT (i.second.size() == 100);
            }
          }

          AND_THEN("Verify that the ranges are occupied")
            {
              uintptr_t addr = 0x10010;
              auto key = map.in_range(addr);

              EXPECT(key > 0);

              // Verify that every address in all the ranges report a conflict
              for (uintptr_t i = 0x10000; i < 0x10000 + count * size; i += 1){
                auto overlap = map.in_range(i);
                EXPECT(overlap);
              }

              EXPECT(not map.in_range(0));
              EXPECT(not map.in_range(0x20000));
              EXPECT(not map.in_range(0x30000));
            }
        }
    }
}

// We can't link against the 32-bit version of IncludeOS (os.a)
// TODOD: This is a terrible hack - we need Linux-build of os.a
#include <kernel/memmap.cpp>
<commit_msg>memmap/test: 100% test coverage for memmap + fixed off-by-one<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#define GSL_THROW_ON_CONTRACT_VIOLATION
#define NO_INFO 1
#include <common.cxx>
#include <iostream>
#include <kernel/memmap.hpp>

CASE ("Using the fixed memory range class")
{
    GIVEN ("A fixed memory range over raw sequence of bytes")
    {
      // A dynamically allocated "raw pool" of bytes
      // @note : In the kernel memory map these would be physical ranges
      char* seq = const_cast<char*>("Spans provide a safer way to access memory");
      Fixed_memory_range range(reinterpret_cast<uintptr_t>(seq + 16),
                                 reinterpret_cast<uintptr_t>(seq + 20), "Demo range",
                               "A range inside a local pool");

      auto seq_start = seq + 16;
      auto seq_end = seq + 20;
      EXPECT(range.size() == seq_end - seq_start + 1);
      EXPECT(std::string(range.name()) == std::string("Demo range"));

      THEN("You can iterate safely over that range, and not out of bounds"){
        for (auto i : range)
          EXPECT(i);

        auto i = range.begin();
        for (; i != range.end(); i++)
          EXPECT(*i);

        EXPECT_THROWS(++i);
        EXPECT_THROWS(i++);

      }

      AND_THEN("You can check if any address is within that range") {

        EXPECT(not range.in_range(1));
        EXPECT(not range.in_range((uintptr_t)seq));
        EXPECT(range.in_range((uintptr_t)seq_start));
        EXPECT(range.in_range((uintptr_t)seq_end));
        EXPECT(not range.in_range((uintptr_t)seq + 22));
      }

      AND_THEN("You can resize that range (but you should let the memory map do that)")
        {
          auto sz = range.size();
          range.resize(range.size() + 100);
          EXPECT(range.size() == sz + 100);
          range.resize(range.size() + 10000);
          EXPECT(range.size() == sz + 10100);
        }
    }
}

CASE("Construct a range with illegal parameters")
{
  EXPECT_THROWS((Fixed_memory_range{(uintptr_t)1000, (uintptr_t)10, "Negative", "A range going backwards"}));
  EXPECT_THROWS((Fixed_memory_range{(uintptr_t)1, (uintptr_t)Fixed_memory_range::span_max() + 100, "Too big", "A range > max of ptrdiff_t"}));
}

CASE ("Using the kernel memory map") {

  GIVEN ("An instance of the memory map with a named range")
    {
      Memory_map map{};
      EXPECT(map.size() == 0);
      EXPECT(not map.in_range(0));
      EXPECT(not map.in_range(0xff));
      EXPECT(not map.in_range(0xffff));
      uintptr_t init_key = 0xff;
      uintptr_t init_end = 0xffff;
      auto init_size = init_end - init_key + 1;
      map.assign_range({init_key, init_end, "Initial", "The first range"});
      EXPECT(map.size() == 1);
      EXPECT(not map.empty());
      auto& range_init = map.at(init_key);
      EXPECT(range_init.in_use() == range_init.size());

      THEN("A copy of that range is identical")
        {
          auto& range = map.at(init_key);
          Fixed_memory_range my_copy = range;
          EXPECT(range.size() == my_copy.size());
          EXPECT(range.in_use() == my_copy.in_use());
          EXPECT(range.addr_start() == my_copy.addr_start());
          EXPECT(range.addr_end() == my_copy.addr_end());
          EXPECT(range.to_string() == my_copy.to_string());
        }

      AND_THEN("The range object can be moved")
        {
          auto& range = map.at(init_key);
          Fixed_memory_range my_copy = std::move(range);
          EXPECT(range.size() == my_copy.size());
          EXPECT(range.in_use() == my_copy.in_use());
          EXPECT(range.addr_start() == my_copy.addr_start());
          EXPECT(range.addr_end() == my_copy.addr_end());
          EXPECT(range.to_string() == my_copy.to_string());
        }

      AND_THEN("You can fetch that range using start address as key")
        {
          auto& range = map.at(init_key);
          EXPECT(range.size() == init_end - init_key + 1);

        }

      AND_THEN("You can ask the memory map if an address is in that range")
        {
          EXPECT(map.in_range(0xff1) == init_key);
          EXPECT(map.at(map.in_range(0xfff)).addr_start() == init_key);
          EXPECT(map.at(map.in_range(0xfffa)).addr_start() == init_key);
          EXPECT_NOT(map.in_range(2));
          EXPECT_NOT(map.in_range(0xf));
          EXPECT_NOT(map.in_range(0xffffff));

          // 0 is not a valid key (spans can start at address 0)
          EXPECT_THROWS(map.at(map.in_range(0)));
        }

      AND_THEN("You can increase the size of that range since nothing is above")
        {
          EXPECT(map.resize(init_key, init_size + 1) == init_size + 1);
          EXPECT(map.resize(init_key, init_size + 100) == init_size + 100);
        }

      AND_THEN("You can't downsize that range, since in_use is all of it by default")
        {
          EXPECT_THROWS(map.resize(init_key, init_size));
          EXPECT_THROWS(map.resize(init_key, 5));
        }

      AND_WHEN("You provide a custom in_use delegate you can downsize")
        {

          auto key = map.at(init_key).addr_end() + 1;
          map.assign_range({key, key + 1000, "Resizable",
                "A resizable range", []()->ptrdiff_t{ return 4; }});

          auto res = map.resize(key, 5);
          EXPECT(res == 5);
          EXPECT(map.at(key).size() == res);
          EXPECT(map.resize(key, 100) == 100);
          EXPECT(map.resize(key, 200) == 200);
          EXPECT(map.resize(key, 20000) == 20000);

          THEN("You still can't downsize to less than what it currently uses")
            {

              EXPECT_THROWS(map.resize(key, 3));

              AND_THEN("If you assign a range above it, you can't increase it further")
                {

                  auto& last_range = map.at(key);
                  auto key2 = last_range.addr_end() + 1;
                  map.assign_range({key2, key2 + 1000, "Above Resizable",
                    "A barrier for resizable"});

                  EXPECT_THROWS(map.resize(key, last_range.size() + 1));
                  EXPECT_THROWS(map.resize(key, last_range.size() + 100));
                }
            }
        }

      AND_THEN("You can't insert an overlapping range")
        {
          EXPECT_THROWS(map.assign_range({0x1, 0xfff, "Range 2", "Overlapping beginning of Range 1"}));
          EXPECT_THROWS(map.assign_range({0xfff, 0xfffff, "Range 2", "Overlapping end of Range 1"}));

          uintptr_t rng2_key = 0x30000;
          uintptr_t rng2_end = 0xfffff;
          EXPECT(map.assign_range({rng2_key, rng2_end, "Range 2", "OK range above initial"}).addr_start() == rng2_key);

          // A range where end-address only is with the second range
          EXPECT_THROWS(map.assign_range({0x20000, 0x40000, "Range 3", "Between Range 1 and Range 2"}));

          // A range where start-address is in the first of the two ranges
          EXPECT_THROWS(map.assign_range({0xfff0, 0x20000, "Range 3", "Between Range 1 and Range 2"}));

          /** Pretty print
          for (auto i : map)
            std::cout << "Range: " << i.second.to_string() << "\n";
          **/
        }

      AND_THEN("You can't insert an embedded  range")
        {
          EXPECT_THROWS(map.assign_range({0xfff, 0xfffa, "Range 4", "Embedded in range 1"}));
        }

      AND_WHEN("You've inserted several ranges you can iterate over them")
        {

          uintptr_t start = 0x10000;
          const size_t size = 100;
          const size_t count = 20;

          for (auto i = start; i < start + count * size; i += size) {
            Fixed_memory_range rng = {i , i + size - 1,"demo",
                                      std::string("The ") + std::to_string(i) + std::string("'th range")};
            map.assign_range(std::move(rng));
            //std::cout << "Demo range for iteration: " << rng.to_string() << "\n";
          }

          EXPECT(map.size() == count + 1);

          for (auto i : map) {
            if (std::string(i.second.name()) == "demo") {
              EXPECT (i.second.size() == 100);
            }
          }

          AND_THEN("Verify that the ranges are occupied")
            {
              uintptr_t addr = 0x10010;
              auto key = map.in_range(addr);

              EXPECT(key > 0);

              // Verify that every address in all the ranges report a conflict
              for (uintptr_t i = 0x10000; i < 0x10000 + count * size; i += 1){
                auto overlap = map.in_range(i);
                //std::cout << "i: " << std::hex << i << " overlaps with "  << overlap << "\n";
                EXPECT(overlap);
              }

              EXPECT(not map.in_range(0));
              EXPECT(not map.in_range(0x20000));
              EXPECT(not map.in_range(0x30000));
            }
        }
    }
}

// We can't link against the 32-bit version of IncludeOS (os.a)
// TODOD: This is a terrible hack - we need Linux-build of os.a
#include <kernel/memmap.cpp>
<|endoftext|>


<commit_before><commit_msg>updata pr<commit_after>sjdfijsdfjdsidl{;P
<|endoftext|>