@Override public Set<ResourceReference> getProvidedResources() { Set<ResourceReference> provided = new HashSet<ResourceReference>(); /* * add all provided resources declared at all levels of abstraction */ Component ancestor = this; while (ancestor != null) { provided.addAll(ancestor.getDeclaration().getProvidedResources()); ancestor = ancestor.getGroup(); } return Collections.unmodifiableSet(provided); }
/** * Tries to find the definition of attribute "attr" associated with component "component". Returns * null if the attribute is not explicitly defined * * @param component * @param attr * @return */ public PropertyDefinition getAttrDefinition(String attr) { // PropertyDefinition definition = // getDeclaration().getPropertyDefinition(attr); // if (definition != null) { // return definition; // } PropertyDefinition definition = null; Component group = this; // .getGroup(); while (group != null) { definition = group.getDeclaration().getPropertyDefinition(attr); if (definition != null) { return definition; } group = group.getGroup(); } return null; }
/** * Given a relation declared in this component, checks if the provided override relation matches * the relation declaration. * * <p>To be applied on a component C, the override must be such that : id matches the override id * source must be the name of C or of an ancestor of C. target must be the same type (resource of * component, and its name must match). */ public boolean matchOverride(RelationDeclaration relation, RelationDeclaration override) { // Overrides are currently only valid for instance boolean match = (this instanceof Instance); if (!match) { return false; } // Check if override source matches this component or one of its // ancestors match = false; Component group = this; while (group != null && !match) { match = override.refines(group.getDeclaration().getReference(), relation); group = group.getGroup(); } return match; }
/** * To be called once the Apam entity is fully initialized. * * <p>Computes all its attributes, including inheritance. Checks if initial properties are * consistent with the declarations. * * <p>NOTE this method is also called when the owner changes, to force recalculation of * substitutions that depend on the current owner. */ private void initializeProperties(Map<String, String> initialProperties) { Component group = getGroup(); /* * Currently the instance declaration may include invalid properties. * * For declared instances this should not happen as the declaration is validated at build-time. For dynamically * created instances (using the APAM API or the apform API directly) this should be validated by this method. * * However, there are many properties added by the iPOJO apform layer that need to be ignored, so we simply * silently ignore all invalid properties. * * TODO We should be able to distinguish properties specified by the user that must be validated, from properties * used internally by the iPOJO apform. */ Set<String> invalidDeclaredProperties = new HashSet<String>(); for (String property : getDeclaration().getProperties().keySet()) { boolean isDefined = getDeclaration().isDefined(property) || (group != null && group.getPropertyDefinition(property) != null); if (!isDefined) { invalidDeclaredProperties.add(property); } if (group != null && group.getProperty(property) != null) { invalidDeclaredProperties.add(property); } } getDeclaration().getProperties().keySet().removeAll(invalidDeclaredProperties); /* * Merge initial and declared properties. * */ Map<String, String> fullInitialProperties = new HashMap<String, String>(getDeclaration().getProperties()); if (initialProperties != null) { fullInitialProperties.putAll(initialProperties); fullInitialProperties.remove("instance.name"); } /* * NOTE In the case of change owner, the initial properties include inherited values from the group, * we ignore them to avoid false error messages, they will be added later by the normal inheritance * mechanism * * TODO Distinguish the case of change owner from a real initialization */ if (initialProperties != null && group != null) { for (Map.Entry<String, String> initialProperty : initialProperties.entrySet()) { if (group.getProperty(initialProperty.getKey()) != null && group.getProperty(initialProperty.getKey()).equals(initialProperty.getValue())) { fullInitialProperties.remove(initialProperty.getKey()); } } } // start cleaning the properties (normally empty) clear(); /* * First add the valid attributes. */ for (Map.Entry<String, String> initialProperty : fullInitialProperties.entrySet()) { PropertyDefinition def = validDef(initialProperty.getKey(), true); if (def != null) { Object val = Attribute.checkAttrType( initialProperty.getKey(), initialProperty.getValue(), def.getType()); if (val != null) { put(initialProperty.getKey(), val); } } } /* * then add those coming from its group, avoiding overloads. */ if (group != null) { for (String attr : group.getAllProperties().keySet()) { if (get(attr) == null) { put(attr, ((ComponentImpl) group).get(attr)); } } } /* * Add the default values specified in the group for properties not explicitly specified */ if (group != null) { for (PropertyDefinition definition : group.getDeclaration().getPropertyDefinitions()) { if (definition.hasDefaultValue() && get(definition.getName()) == null && definition.getInjected() != InjectedPropertyPolicy.INTERNAL) { Object val = Attribute.checkAttrType( definition.getName(), definition.getDefaultValue(), definition.getType()); if (val != null) { put(definition.getName(), val); } } } } /* * Set the attribute for the final attributes */ put(CST.SHARED, Boolean.toString(isShared())); put(CST.SINGLETON, Boolean.toString(isSingleton())); put(CST.INSTANTIABLE, Boolean.toString(isInstantiable())); /* * Finally add the specific attributes. * Should be the only place where instanceof is used. */ put(CST.NAME, apform.getDeclaration().getName()); if (this instanceof Specification) { put(CST.SPECNAME, apform.getDeclaration().getName()); } else if (this instanceof Implementation) { put(CST.IMPLNAME, apform.getDeclaration().getName()); if (this instanceof CompositeType) { put(CST.APAM_COMPOSITETYPE, CST.V_TRUE); } } else if (this instanceof Instance) { put(CST.INSTNAME, apform.getDeclaration().getName()); if (this instanceof Composite) { Composite composite = (Composite) this; put(CST.APAM_COMPOSITE, CST.V_TRUE); if (composite.getMainInst() != null) { put(CST.APAM_MAIN_INSTANCE, composite.getMainInst().getName()); } } } /* * and propagate, to the platform and to members, in case the spec has been created after the implem */ for (Map.Entry<String, Object> entry : this.entrySet()) { for (Component member : getMembers()) { ((ComponentImpl) member).propagate(entry.getKey(), entry.getValue()); } } }
/** * Provided a component, compute its effective relations definition, adding group constraint and * flags. It is supposed to be correct !! No failure expected * * <p>Does not add those dependencies defined "above". For relations refined locally, merge the * local definition with the group definition. * * <p>For instances only, add the relation definition overridden by the composite. * * <p>Remove those links that are not valid with the computed relation definition (for * changeOwner) */ private void initializeRelations() { /* * First we need to compute the list of relations that must be locally * defined in this component. We consider locally defined relation * declarations and overridden inherited relations. */ Set<RelationDeclaration> overrides = null; if (this instanceof Instance) { overrides = ((Instance) this) .getComposite() .getCompType() .getCompoDeclaration() .getOverridenDependencies(); } else overrides = Collections.emptySet(); Set<RelationDeclaration> localRelations = new HashSet<RelationDeclaration>(); Set<String> processed = new HashSet<String>(); Component group = this; while (group != null) { for (RelationDeclaration relationDeclaration : group.getDeclaration().getRelations()) { /* * Ignore relations already processed at a lower level */ if (processed.contains(relationDeclaration.getIdentifier())) { continue; } /* * Check overridden relations */ boolean matchOverride = false; for (RelationDeclaration override : overrides) { // for (RelationDeclaration override : overrides != null ? overrides // : Collections.<RelationDeclaration> emptySet()) { if (matchOverride(relationDeclaration, override)) { relationDeclaration = relationDeclaration.overriddenBy(override); matchOverride = true; } } /* * Process locally declared and inherited overridden relations */ if (group == this || matchOverride) { localRelations.add(relationDeclaration); processed.add(relationDeclaration.getIdentifier()); } } group = group.getGroup(); } /* * Define all the local relations definition of this component */ for (RelationDeclaration relationDeclaration : localRelations) { /* * Local declarations may be partial definitions, we need to compute * the complete declaration by refining the ancestor definition. */ RelationDefinition base = this.getRelation(relationDeclaration.getIdentifier()); relationDeclaration = (base == null) ? relationDeclaration : ((RelationDefinitionImpl) base).refinedBy(relationDeclaration); relDef.put( relationDeclaration.getIdentifier(), new RelationDefinitionImpl(relationDeclaration)); } /* * If the component has links, remove those that are invalid (for changeOwner) * Also remove the link if it is a promotion, since we are no longer in the same composite */ for (Link localLink : getLocalLinks()) { if (localLink.isPromotion() || !localLink.isValid()) localLink.remove(); } for (Link incoming : getInvLinks()) { if (incoming.isPromotion() || !incoming.isValid()) incoming.remove(); } }