Package: support for variants
- Catalog keeps a map from variant IDs to packages - Package caches its ID - Refreshing a catalog updates existing Package instances Dropping a package from a Catalog will now warn, need to decide a real policy for this scenario.
This commit is contained in:
parent
5024b62c0a
commit
bb5e07d958
@ -245,18 +245,46 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
|
|||||||
// copy everything except package children?
|
// copy everything except package children?
|
||||||
m_props = new SGPropertyNode;
|
m_props = new SGPropertyNode;
|
||||||
|
|
||||||
|
m_variantDict.clear(); // will rebuild during parse
|
||||||
|
std::set<PackageRef> orphans;
|
||||||
|
orphans.insert(m_packages.begin(), m_packages.end());
|
||||||
|
|
||||||
int nChildren = aProps->nChildren();
|
int nChildren = aProps->nChildren();
|
||||||
for (int i = 0; i < nChildren; i++) {
|
for (int i = 0; i < nChildren; i++) {
|
||||||
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
const SGPropertyNode* pkgProps = aProps->getChild(i);
|
||||||
if (strcmp(pkgProps->getName(), "package") == 0) {
|
if (strcmp(pkgProps->getName(), "package") == 0) {
|
||||||
PackageRef p = new Package(pkgProps, this);
|
PackageRef p = getPackageById(pkgProps->getStringValue("id"));
|
||||||
|
if (p) {
|
||||||
|
// existing package
|
||||||
|
p->updateFromProps(pkgProps);
|
||||||
|
orphans.erase(p); // not an orphan
|
||||||
|
} else {
|
||||||
|
// new package
|
||||||
|
p = new Package(pkgProps, this);
|
||||||
m_packages.push_back(p);
|
m_packages.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_list vars(p->variants());
|
||||||
|
for (string_list::iterator it = vars.begin(); it != vars.end(); ++it) {
|
||||||
|
m_variantDict[*it] = p.ptr();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SGPropertyNode* c = m_props->getChild(pkgProps->getName(), pkgProps->getIndex(), true);
|
SGPropertyNode* c = m_props->getChild(pkgProps->getName(), pkgProps->getIndex(), true);
|
||||||
copyProperties(pkgProps, c);
|
copyProperties(pkgProps, c);
|
||||||
}
|
}
|
||||||
} // of children iteration
|
} // of children iteration
|
||||||
|
|
||||||
|
if (!orphans.empty()) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "have orphan packages: will become inaccesible");
|
||||||
|
std::set<PackageRef>::iterator it;
|
||||||
|
for (it = orphans.begin(); it != orphans.end(); ++it) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_WARN, "\torphan package:" << (*it)->qualifiedId());
|
||||||
|
PackageList::iterator pit = std::find(m_packages.begin(), m_packages.end(), *it);
|
||||||
|
assert(pit != m_packages.end());
|
||||||
|
m_packages.erase(pit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_url.empty()) {
|
if (!m_url.empty()) {
|
||||||
if (m_url != m_props->getStringValue("url")) {
|
if (m_url != m_props->getStringValue("url")) {
|
||||||
// this effectively allows packages to migrate to new locations,
|
// this effectively allows packages to migrate to new locations,
|
||||||
@ -280,13 +308,13 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
|
|||||||
|
|
||||||
PackageRef Catalog::getPackageById(const std::string& aId) const
|
PackageRef Catalog::getPackageById(const std::string& aId) const
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(PackageRef p, m_packages) {
|
// search the variant dict here, so looking up aircraft variants
|
||||||
if (p->id() == aId) {
|
// works as expected.
|
||||||
return p;
|
PackageWeakMap::const_iterator it = m_variantDict.find(aId);
|
||||||
}
|
if (it == m_variantDict.end())
|
||||||
}
|
return NULL;
|
||||||
|
|
||||||
return NULL; // not found
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Catalog::id() const
|
std::string Catalog::id() const
|
||||||
|
@ -144,6 +144,9 @@ private:
|
|||||||
PackageList m_packages;
|
PackageList m_packages;
|
||||||
time_t m_retrievedTime;
|
time_t m_retrievedTime;
|
||||||
|
|
||||||
|
typedef std::map<std::string, Package*> PackageWeakMap;
|
||||||
|
PackageWeakMap m_variantDict;
|
||||||
|
|
||||||
// important that this is a weak-ref to Installs,
|
// important that this is a weak-ref to Installs,
|
||||||
// since it is only cleaned up in the Install destructor
|
// since it is only cleaned up in the Install destructor
|
||||||
typedef std::map<PackageRef, Install*> PackageInstallDict;
|
typedef std::map<PackageRef, Install*> PackageInstallDict;
|
||||||
|
@ -46,6 +46,14 @@ void Package::initWithProps(const SGPropertyNode* aProps)
|
|||||||
std::string t(c->getStringValue());
|
std::string t(c->getStringValue());
|
||||||
m_tags.insert(boost::to_lower_copy(t));
|
m_tags.insert(boost::to_lower_copy(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_id = m_props->getStringValue("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Package::updateFromProps(const SGPropertyNode* aProps)
|
||||||
|
{
|
||||||
|
m_tags.clear();
|
||||||
|
initWithProps(aProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Package::matches(const SGPropertyNode* aFilter) const
|
bool Package::matches(const SGPropertyNode* aFilter) const
|
||||||
@ -133,7 +141,7 @@ InstallRef Package::existingInstall() const
|
|||||||
|
|
||||||
std::string Package::id() const
|
std::string Package::id() const
|
||||||
{
|
{
|
||||||
return m_props->getStringValue("id");
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Package::qualifiedId() const
|
std::string Package::qualifiedId() const
|
||||||
@ -241,6 +249,34 @@ PackageList Package::dependencies() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string_list Package::variants() const
|
||||||
|
{
|
||||||
|
string_list result;
|
||||||
|
result.push_back(id());
|
||||||
|
|
||||||
|
BOOST_FOREACH(SGPropertyNode* var, m_props->getChildren("variant")) {
|
||||||
|
result.push_back(var->getStringValue("id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Package::nameForVariant(const std::string& vid) const
|
||||||
|
{
|
||||||
|
if (vid == id()) {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(SGPropertyNode* var, m_props->getChildren("variant")) {
|
||||||
|
if (vid == var->getStringValue("id")) {
|
||||||
|
return var->getStringValue("name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
throw sg_exception("Unknow variant +" + vid + " in package " + id());
|
||||||
|
}
|
||||||
|
|
||||||
} // of namespace pkg
|
} // of namespace pkg
|
||||||
|
|
||||||
} // of namespace simgear
|
} // of namespace simgear
|
||||||
|
@ -60,6 +60,12 @@ public:
|
|||||||
|
|
||||||
std::string id() const;
|
std::string id() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant IDs. Note the primary ID will always be included as
|
||||||
|
* variants()[0], to simplify enumerating all variants
|
||||||
|
*/
|
||||||
|
string_list variants() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fully-qualified ID, including our catalog'd ID
|
* Fully-qualified ID, including our catalog'd ID
|
||||||
*/
|
*/
|
||||||
@ -71,6 +77,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Human readable name of a variant
|
||||||
|
*/
|
||||||
|
std::string nameForVariant(const std::string& vid) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* syntactic sugar to get the localised description
|
* syntactic sugar to get the localised description
|
||||||
*/
|
*/
|
||||||
@ -119,9 +130,12 @@ private:
|
|||||||
|
|
||||||
void initWithProps(const SGPropertyNode* aProps);
|
void initWithProps(const SGPropertyNode* aProps);
|
||||||
|
|
||||||
|
void updateFromProps(const SGPropertyNode* aProps);
|
||||||
|
|
||||||
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const;
|
||||||
|
|
||||||
SGPropertyNode_ptr m_props;
|
SGPropertyNode_ptr m_props;
|
||||||
|
std::string m_id;
|
||||||
string_set m_tags;
|
string_set m_tags;
|
||||||
CatalogRef m_catalog;
|
CatalogRef m_catalog;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user