/**
 * @param mapping A Python dictionary instance
 * @return A new C++ PropertyManager instance
 */
boost::shared_ptr<Kernel::PropertyManager>
createPropertyManager(const boost::python::dict &mapping) {
  auto pmgr = boost::make_shared<PropertyManager>();
#if PY_MAJOR_VERSION >= 3
  object view(mapping.attr("items")());
  object itemIter(handle<>(PyObject_GetIter(view.ptr())));
#else
  object itemIter(mapping.attr("iteritems")());
#endif
  auto length = len(mapping);
  for (ssize_t i = 0; i < length; ++i) {
    const object keyValue(handle<>(PyIter_Next(itemIter.ptr())));
    const std::string cppkey = extract<std::string>(keyValue[0])();
    pmgr->declareProperty(PropertyWithValueFactory::create(cppkey, keyValue[1],
                                                           Direction::Input));
  }
  return pmgr;
}
nsresult
txStylesheet::doneCompiling()
{
    nsresult rv = NS_OK;
    // Collect all importframes into a single ordered list
    txListIterator frameIter(&mImportFrames);
    rv = frameIter.addAfter(mRootFrame);
    NS_ENSURE_SUCCESS(rv, rv);
    
    mRootFrame = nullptr;
    frameIter.next();
    rv = addFrames(frameIter);
    NS_ENSURE_SUCCESS(rv, rv);

    // Loop through importframes in decreasing-precedence-order and process
    // all items
    frameIter.reset();
    ImportFrame* frame;
    while ((frame = static_cast<ImportFrame*>(frameIter.next()))) {
        nsTArray<txStripSpaceTest*> frameStripSpaceTests;

        txListIterator itemIter(&frame->mToplevelItems);
        itemIter.resetToEnd();
        txToplevelItem* item;
        while ((item = static_cast<txToplevelItem*>(itemIter.previous()))) {
            switch (item->getType()) {
                case txToplevelItem::attributeSet:
                {
                    rv = addAttributeSet(static_cast<txAttributeSetItem*>
                                                    (item));
                    NS_ENSURE_SUCCESS(rv, rv);
                    break;
                }
                case txToplevelItem::dummy:
                case txToplevelItem::import:
                {
                    break;
                }
                case txToplevelItem::output:
                {
                    mOutputFormat.merge(static_cast<txOutputItem*>(item)->mFormat);
                    break;
                }
                case txToplevelItem::stripSpace:
                {
                    rv = addStripSpace(static_cast<txStripSpaceItem*>(item),
                                       frameStripSpaceTests);
                    NS_ENSURE_SUCCESS(rv, rv);
                    break;
                }
                case txToplevelItem::templ:
                {
                    rv = addTemplate(static_cast<txTemplateItem*>(item),
                                     frame);
                    NS_ENSURE_SUCCESS(rv, rv);

                    break;
                }
                case txToplevelItem::variable:
                {
                    rv = addGlobalVariable(static_cast<txVariableItem*>
                                                      (item));
                    NS_ENSURE_SUCCESS(rv, rv);

                    break;
                }
            }
            delete item;
            itemIter.remove(); //remove() moves to the previous
            itemIter.next();
        }
        if (!mStripSpaceTests.AppendElements(frameStripSpaceTests)) {
            return NS_ERROR_OUT_OF_MEMORY;
        }
        
        frameStripSpaceTests.Clear();
    }

    if (!mDecimalFormats.get(txExpandedName())) {
        nsAutoPtr<txDecimalFormat> format(new txDecimalFormat);
        NS_ENSURE_TRUE(format, NS_ERROR_OUT_OF_MEMORY);
        
        rv = mDecimalFormats.add(txExpandedName(), format);
        NS_ENSURE_SUCCESS(rv, rv);
        
        format.forget();
    }

    return NS_OK;
}
String JavaVMSingleton::computeClassPath(const zorba::StaticContext* aStaticContext)
{
  String cp;

  // get classpath from global Properties
  PropertiesGlobal * properties = Zorba::getInstance(NULL)->getPropertiesGlobal();
  std::string globalClassPath;
  properties->getJVMClassPath(globalClassPath);
  cp += globalClassPath;

  std::vector<String> lCPV;
  aStaticContext->getFullLibPath(lCPV);

  for (std::vector<String>::iterator lIter = lCPV.begin();
       lIter != lCPV.end(); ++lIter)
  {
    // verify it contains a jars dir
    String jarsDir( *lIter );
    fs::append( jarsDir, "jars" );

    if ( fs::get_type( jarsDir ) == fs::directory )
    {
      fs::iterator itemIter( jarsDir );

      while ( itemIter.next() )
      {
        String itemFile( jarsDir );
        fs::append( itemFile, itemIter->name );
        if ( fs::get_type( itemFile ) == fs::file )
        {
          std::string suffix = "-classpath.txt";
          size_t found;
          found = itemFile.rfind(suffix);
          if (found!=std::string::npos &&
              found + suffix.length() == itemFile.length() )
          {
            std::auto_ptr<std::istream> pathFile;
            pathFile.reset(new std::ifstream (itemFile.c_str ()));
            if (!pathFile->good() || pathFile->eof() )
            {
              std::cerr << "file {" << itemFile << "} not found or not readable." << std::endl;
              throw itemFile;
            }

            // read file
            char line[1024];
            while( !pathFile->eof() && !pathFile->bad() && !pathFile->fail())
            {
              pathFile->getline(line, sizeof(line));
              std::string lineStr(line);

              if ( lineStr.size() > 0 ) {
                cp += fs::path_separator;
                cp += fs::normalize_path( lineStr, jarsDir );
              }
            }
          }
        }
      }
    }
  }

  properties->setJVMClassPath(cp.str());

  return cp;
}