bool ProfileDB::internalMatchProfile(Profile* profile, vector<Capability>& requiredCapabilites, vector<Capability>& optionalCapabilites, string& matchToken) { bool match = true; // When can we NOT reuse a specific runtime? // Only if fragmentation is set to BUILDTIME and if either a) one supports the capability and // the other does not OR b) the capability value differs. // So we add strings to create a unique match token for every // runtime that need be built for (vector<Capability>::iterator capability = requiredCapabilites.begin(); capability != requiredCapabilites.end(); capability++) { Capability matchedCapability = profile->getCapability( capability->getName()); CapabilityState matchedState = matchedCapability.getState(); // Ok, so we don't support this, bail out! if (matchedState == NOT_IMPLEMENTED || matchedState == UNSUPPORTED) { match = false; } Fragmentation fragmentation = matchedCapability.getFragmentation(); string valueStr = fragmentation == BUILDTIME ? matchedCapability.getValue() : ""; matchToken.append(valueStr); matchToken.append("|"); } // So, the optional capabilities are matched in a different way. // We add stuff to the matchTokens string to produce a string that // is unique to the optional capabilities being matched. for (vector<Capability>::iterator capability = optionalCapabilites.begin(); capability != optionalCapabilites.end(); capability++) { Capability matchedCapability = profile->getCapability( capability->getName()); CapabilityState matchedState = matchedCapability.getState(); Fragmentation fragmentation = matchedCapability.getFragmentation(); string valueStr = fragmentation == BUILDTIME ? matchedCapability.getValue() : ""; bool capSupported = fragmentation == BUILDTIME && (matchedState == NOT_IMPLEMENTED || matchedState == UNSUPPORTED); matchToken.append((capSupported ? "+" : "-") + valueStr); matchToken.append("|"); } // Finally we add PROPERTIES of the runtime which are buildtime fragmented. // For example, different device types or icon sizes should always generate // a unique runtime. set<string> allCapabilities = profile->getCapabilities(); for (set<string>::iterator allCapabilitesIt = allCapabilities.begin(); allCapabilitesIt != allCapabilities.end(); allCapabilitesIt++) { string capabilityName = *allCapabilitesIt; Capability capability = profile->getCapability(capabilityName); if (capability.getType() == "property") { Fragmentation fragmentation = capability.getFragmentation(); string valueStr = fragmentation == BUILDTIME ? capability.getValue() : "-"; matchToken.append(valueStr); matchToken.append("|"); } } return match; }
static void xmlStart(void *data, const char *tagName, const char **attributes) { ParserState* state = (ParserState*) data; ProfileDB* db = state->db; Profile* profile = state->profile; if (!strcmp(ELEMENT_PLATFORM, tagName)) { const char* parentProfile = findAttr(ATTR_INHERIT, attributes); if (parentProfile) { Profile* parent = db->findProfile(parentProfile, state->alreadyFound); if (parent == NULL) { error( state, string( "This platform element refers to an invalid parent profile: ") + parentProfile); } else { profile->setParent(parent); } } const char* abstract = findAttr(ATTR_ABSTRACT, attributes); bool isAbstract = abstract && !strcmp("true", abstract); const char* family = findAttr(ATTR_FAMILY, attributes); if (!family) { error( state, string("No family attribute defined: ") + profile->getProfileName()); } const char* variant = findAttr(ATTR_VARIANT, attributes); if (!isAbstract && !variant) { error( state, string("No variant attribute defined: ") + profile->getProfileName()); } const char* runtime = findAttr(ATTR_RUNTIME, attributes); if (!isAbstract && !runtime) { error( state, string("No runtime attribute defined: ") + profile->getProfileName()); } if (!variant) variant = ""; if (!runtime) runtime = ""; const char* slash = strlen(variant) > 0 ? "/" : ""; if (!equalsIgnoreCaseASCII(string(family) + slash + string(variant), profile->getProfileName())) { error( state, string("Expected family (") + family + string( ") and variant (") + variant + string(") to match ") + profile->getProfileName()); } profile->setFamily(string(family)); profile->setVariant(string(variant)); profile->setRuntime(string(runtime)); profile->setAbstract(isAbstract); } else if (!strcmp(ELEMENT_CAPABILITY, tagName)) { CapabilityState capabilityState; Capability* parentCapability = NULL; string prefix = getCapabilityPrefix(state->capabilityStack); if (!state->capabilityStack.empty()) { parentCapability = &(state->capabilityStack.back()); capabilityState = parentCapability->getState(); } const char* capabilityName = findAttr(ATTR_NAME, attributes); const char* capabilityStateStr = findAttr(ATTR_STATE, attributes); const char* fragmentationStr = findAttr(ATTR_FRAGMENTATION, attributes); const char* valueStr = findAttr(ATTR_VALUE, attributes); const char* typeStr = findAttr(ATTR_TYPE, attributes); if (!capabilityStateStr && !parentCapability) { capabilityState = UNSUPPORTED; } else if (!strcmp(capabilityStateStr, "SUPPORTED")) { capabilityState = SUPPORTED; } else if (!strcmp(capabilityStateStr, "UNSUPPORTED")) { capabilityState = UNSUPPORTED; } else if (!strcmp(capabilityStateStr, "NOT_IMPLEMENTED")) { capabilityState = NOT_IMPLEMENTED; } else if (!strcmp(capabilityStateStr, "REQUIRES_PERMISSION")) { capabilityState = REQUIRES_PERMISSION; } else if (!strcmp(capabilityStateStr, "REQUIRES_PRIVILEGED_PERMISSION")) { capabilityState = REQUIRES_PRIVILEGED_PERMISSION; } else { error(state, string("Unknown state: ") + capabilityStateStr); } Fragmentation fragmentation = fragmentationStr && !strcmp("buildtime", fragmentationStr) ? BUILDTIME : RUNTIME; string value = valueStr ? string(valueStr) : string(); string type = typeStr ? string(typeStr) : (value.length() == 0 ? string() : PROPERTY_TYPE); Capability capability = Capability(prefix + capabilityName, type, value, capabilityState, fragmentation); state->profile->addCapability(capability); state->capabilityStack.push_back(capability); } }