This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository eugene. See https://gitlab.nuiton.org/nuiton/eugene.git commit 902ad6a0573401464e7e7df6606eb4c2119f6516 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sat Sep 10 10:56:34 2016 +0200 Introduce extension package + model extension file parser --- .../extension/CompactModelExtensionFileParser.java | 173 ++++++ .../extension/FlatModelExtensionFileParser.java | 214 ++++++++ .../reader/extension/LoadModelExtension.java | 585 +++++++++++++++++++++ .../reader/extension/ModelExtensionFileParser.java | 16 + .../ModelExtensionFileParserCallback.java | 28 + 5 files changed, 1016 insertions(+) diff --git a/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/CompactModelExtensionFileParser.java b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/CompactModelExtensionFileParser.java new file mode 100644 index 0000000..3f18ac4 --- /dev/null +++ b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/CompactModelExtensionFileParser.java @@ -0,0 +1,173 @@ +package org.nuiton.eugene.models.object.reader.extension; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; + +/** + * Created on 09/09/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class CompactModelExtensionFileParser implements ModelExtensionFileParser { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CompactModelExtensionFileParser.class); + + enum Scope { + MODEL, + PACKAGE, + CLASS + } + + protected Scope scope; + protected String name; + + @Override + public void parse(File file, ModelExtensionFileParserCallback callback) throws IOException { + + scope = null; + name = null; + + List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); + + for (String line : lines) { + consumeLine(line, callback); + } + + } + + protected void consumeLine(String line, ModelExtensionFileParserCallback callback) { + if (StringUtils.isBlank(line)) { + + // ligne vide + return; + } + if (line.startsWith("#")) { + + // commentaire + return; + } + Scope newScope = getScope(line); + if (newScope != null) { + + // changement de scope + this.scope = newScope; + this.name = null; + return; + } + + Preconditions.checkState(scope != null); + + switch (scope) { + + case MODEL: { + + // la ligne est une tag value ou un stereotype + int index = line.indexOf(' '); + if (index == -1) { + + // stereotype de package + callback.onModelStereotypeFound(line); + + } else { + + // tag value de package + callback.onModelTagValueFound(line.substring(0, index), line.substring(index + 1)); + } + } + break; + case PACKAGE: { + if (line.startsWith(" ")) { + + Preconditions.checkState(name != null, "Pas de nom de paquetage déclaré"); + + line = line.trim(); + + // la ligne est une tag value ou un stereotype + int index = line.indexOf(' '); + if (index == -1) { + + // stereotype de package + callback.onPackageStereotypeFound(name, line); + } else { + + // tag value de package + callback.onPackageTagValueFound(name, line.substring(0, index), line.substring(index + 1)); + } + + break; + + } + + name = line; + + } + break; + case CLASS: + + if (line.startsWith(" ")) { + + Preconditions.checkState(name != null, "Pas de nom de classe déclaré"); + + line = line.trim(); + + // la ligne est une tag value ou un stereotype + int index = line.indexOf(' '); + if (index == -1) { + + int attributeIndex = line.indexOf('.'); + if (attributeIndex == -1) { + + // stereotype de classe + callback.onClassStereotypeFound(name, line); + } else { + + // stereotype d'attribut + callback.onAttributeStereotypeFound(name, line.substring(0, attributeIndex), line.substring(attributeIndex + 1)); + } + + } else { + + String attributeOrTagValue = line.substring(0, index); + + int attributeIndex = attributeOrTagValue.indexOf('.'); + if (attributeIndex == -1) { + + // tag value de classe + callback.onClassTagValueFound(name, attributeOrTagValue, line.substring(index + 1)); + + + } else { + // tag value d'attribut + callback.onAttributeTagValueFound(name, attributeOrTagValue.substring(0, attributeIndex), attributeOrTagValue.substring(attributeIndex + 1), line.substring(index + 1)); + } + + } + + break; + } + + name = line; + + break; + } + } + + protected Scope getScope(String line) { + for (Scope scope : Scope.values()) { + String scopeStr = "[" + scope.name().toLowerCase() + "]"; + if (line.equals(scopeStr)) { + return scope; + } + } + return null; + } +} diff --git a/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/FlatModelExtensionFileParser.java b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/FlatModelExtensionFileParser.java new file mode 100644 index 0000000..0f19652 --- /dev/null +++ b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/FlatModelExtensionFileParser.java @@ -0,0 +1,214 @@ +package org.nuiton.eugene.models.object.reader.extension; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.models.object.reader.InvalidModelPropertiesException; +import org.nuiton.eugene.models.stereotype.InvalidStereotypeSyntaxException; +import org.nuiton.eugene.models.stereotype.Stereotypes; +import org.nuiton.eugene.models.tagvalue.InvalidTagValueSyntaxException; +import org.nuiton.eugene.models.tagvalue.TagValues; +import org.nuiton.util.RecursiveProperties; +import org.nuiton.util.StringUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; + +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.ATTRIBUTE; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.CLASS; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.MODEL; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.PACKAGE; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.STEREOTYPE; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.TAGVALUE; +import static org.nuiton.eugene.models.object.reader.AbstractObjectModelReader.TAG_VALUE; + +/** + * Created on 09/09/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class FlatModelExtensionFileParser implements ModelExtensionFileParser { + + /** Logger. */ + private static final Log log = LogFactory.getLog(FlatModelExtensionFileParser.class); + + @Override + public void parse(File file, ModelExtensionFileParserCallback callback) throws IOException, InvalidStereotypeSyntaxException, InvalidTagValueSyntaxException { + + Properties prop = new RecursiveProperties(); + + try (Reader inStream = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { + prop.load(inStream); + } + + // get all the tagvalues keys and sort them + List<String> keys = new ArrayList<>(); + CollectionUtils.addAll(keys, prop.keys()); + Collections.sort(keys); + + boolean safe = true; + for (String key : keys) { + String value = prop.getProperty(key); + safe &= consumeKeyValue(key, value, callback); + + } + + if (!safe) { + + String errorMessage = "There is some tag value(s) or stereotype(s) failed to be imported from " + file; + throw new InvalidModelPropertiesException(errorMessage); + + } + + } + + protected boolean consumeKeyValue(String key, String value, ModelExtensionFileParserCallback callback) throws InvalidStereotypeSyntaxException, InvalidTagValueSyntaxException { + + boolean safe = true; + + boolean stereoTypeKey = isStereotype(key); + boolean tagValueTypeKey = isTagValue(key); + + if (log.isDebugEnabled()) { + log.debug("Property: '" + key + "' = " + value); + } + + if (key.startsWith(MODEL)) { + + // model stereotype + if (stereoTypeKey) { + + Set<String> stereotypes = Stereotypes.getStereotypes(value); + for (String stereotype : stereotypes) { + safe &= callback.onModelStereotypeFound(stereotype); + } + return safe; + + } + + // model tag value + if (tagValueTypeKey) { + + Matcher matcher = TagValues.getModelMatcher(key); + + String tag = matcher.group(2); + + return callback.onModelTagValueFound(tag, value); + + } + + throw new InvalidModelPropertiesException(key + " is not a valid model entry."); + + } + + if (key.startsWith(PACKAGE)) { + + // package stereotype or tag value + + if (stereoTypeKey) { + + // package stereotype + Matcher matcher = Stereotypes.getPackageMatcher(key); + + String fqn = matcher.group(1); + fqn = StringUtil.substring(fqn, 0, -1); // remove ended . + + Set<String> stereotypes = Stereotypes.getStereotypes(value); + for (String stereotype : stereotypes) { + safe &= callback.onPackageStereotypeFound(fqn, stereotype); + } + return safe; + + } + + if (tagValueTypeKey) { + + // package tag value + + Matcher matcher = TagValues.getPackageMatcher(key); + + String packageName = matcher.group(1); + packageName = StringUtil.substring(packageName, 0, -1); // remove ended . + String tag = matcher.group(3); + + return callback.onPackageTagValueFound(packageName, tag, value); + + } + + throw new InvalidModelPropertiesException(key + " is not a valid package entry."); + + } + + // element tag value or stereotype + + if (stereoTypeKey) { + + // stereotype property + + // check key is ok + Matcher matcher = Stereotypes.getMatcher(key); + + String fqn = matcher.group(1); + fqn = StringUtil.substring(fqn, 0, -1); // remove ended . + // target is class, attribute or operation + String target = matcher.group(2); + String targetName = matcher.group(3); + + Set<String> stereotypes = Stereotypes.getStereotypes(value); + for (String stereotype : stereotypes) { + + if (CLASS.equals(target)) { + safe &= callback.onClassStereotypeFound(fqn, stereotype); + } else if (ATTRIBUTE.equals(target)) { + safe &= callback.onAttributeStereotypeFound(fqn, targetName, stereotype); + } + } + return safe; + + } + if (tagValueTypeKey) { + + // tag value property + + Matcher matcher = TagValues.getMatcher(key); + + String fqn = matcher.group(1); + fqn = StringUtil.substring(fqn, 0, -1); // remove ended dot + // target is class, attribute or operation + String target = matcher.group(2); + // name of the target (can be null on class) + String targetName = matcher.group(3); + // type is tagvalue + String type = matcher.group(4).toLowerCase(); + // name of the tag value + String tag = matcher.group(5); + + if (CLASS.equals(target)) { + return callback.onClassTagValueFound(fqn, tag, value); + } else if (ATTRIBUTE.equals(target)) { + return callback.onAttributeTagValueFound(fqn, targetName, tag, value); + } + } + + throw new InvalidModelPropertiesException(key + " is not a valid class or attribute entry."); + } + + protected boolean isTagValue(String key) { + return key.contains(TAGVALUE) || key.contains(TAG_VALUE); + } + + protected boolean isStereotype(String key) { + return key.contains(STEREOTYPE); + } + +} diff --git a/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/LoadModelExtension.java b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/LoadModelExtension.java new file mode 100644 index 0000000..b68e576 --- /dev/null +++ b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/LoadModelExtension.java @@ -0,0 +1,585 @@ +package org.nuiton.eugene.models.object.reader.extension; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.EugeneTagValues; +import org.nuiton.eugene.models.object.ObjectModel; +import org.nuiton.eugene.models.object.ObjectModelAssociationClass; +import org.nuiton.eugene.models.object.ObjectModelAttribute; +import org.nuiton.eugene.models.object.ObjectModelClass; +import org.nuiton.eugene.models.object.ObjectModelClassifier; +import org.nuiton.eugene.models.object.ObjectModelPackage; +import org.nuiton.eugene.models.object.xml.ObjectModelAssociationClassImpl; +import org.nuiton.eugene.models.object.xml.ObjectModelClassifierImpl; +import org.nuiton.eugene.models.object.xml.ObjectModelImpl; +import org.nuiton.eugene.models.stereotype.InvalidStereotypeSyntaxException; +import org.nuiton.eugene.models.stereotype.MismatchStereotypeTargetException; +import org.nuiton.eugene.models.stereotype.StereotypeDefinitionProvider; +import org.nuiton.eugene.models.stereotype.StereotypeDefinitionProviders; +import org.nuiton.eugene.models.stereotype.StereotypeNotFoundException; +import org.nuiton.eugene.models.tagvalue.InvalidTagValueSyntaxException; +import org.nuiton.eugene.models.tagvalue.MismatchTagValueTargetException; +import org.nuiton.eugene.models.tagvalue.TagValueDefinitionProvider; +import org.nuiton.eugene.models.tagvalue.TagValueDefinitionProviders; +import org.nuiton.eugene.models.tagvalue.TagValueNotFoundException; + +import java.io.File; +import java.io.IOException; + + +/** + * Created on 09/09/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class LoadModelExtension<M extends ObjectModel> implements ModelExtensionFileParserCallback<M> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(LoadModelExtension.class); + + protected final boolean verbose; + protected final boolean strictLoading; + protected final M model; + protected final TagValueDefinitionProvider tagValueDefinitionProvider; + protected final StereotypeDefinitionProvider stereotypeDefinitionProvider; + + public static <M extends ObjectModel> void loadForFlatModel(boolean verbose, boolean strictLoading, M model, File modelExtension) throws IOException { + FlatModelExtensionFileParser parser = new FlatModelExtensionFileParser(); + try { + new LoadModelExtension<>(verbose, strictLoading, model).load(modelExtension); + } catch (InvalidTagValueSyntaxException | InvalidStereotypeSyntaxException e) { + // FIXME + throw new IllegalStateException(e); + } + + } + + public static <M extends ObjectModel> void loadForCompactModel(boolean verbose, boolean strictLoading, M model, File modelExtension) throws IOException { + CompactModelExtensionFileParser parser = new CompactModelExtensionFileParser(); + try { + new LoadModelExtension<>(verbose, strictLoading, model).load(modelExtension); + } catch (InvalidTagValueSyntaxException | InvalidStereotypeSyntaxException e) { + // FIXME + throw new IllegalStateException(e); + } + + } + + public LoadModelExtension(boolean verbose, boolean strictLoading, M model) { + this.verbose = verbose; + this.strictLoading = strictLoading; + this.model = model; + this.tagValueDefinitionProvider = TagValueDefinitionProviders.newProvider(getClass().getClassLoader(), false); + this.stereotypeDefinitionProvider = StereotypeDefinitionProviders.newProvider(getClass().getClassLoader(), false); + } + + public void load(File modelExtension) throws IOException, InvalidTagValueSyntaxException, InvalidStereotypeSyntaxException { + + ModelExtensionFileParser parser; + if (modelExtension.getName().endsWith(".properties")) { + parser = new FlatModelExtensionFileParser(); + } else { + parser = new CompactModelExtensionFileParser(); + } + parser.parse(modelExtension, this); + + } + + @Override + public boolean onModelTagValueFound(String tag, String value) { + + boolean safe = false; + + try { + tagValueDefinitionProvider.validate(tag, ObjectModel.class); + safe = true; + } catch (TagValueNotFoundException e) { + String message = "Invalid model tag value: the tagvalue '" + tag + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchTagValueTargetException e) { + String message = "Invalid model tag value: this tagvalue '" + tag + "' can not be apply on the model."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if tagValue is deprecated + boolean deprecated = tagValueDefinitionProvider.isDeprecated(tag); + if (deprecated) { + if (log.isWarnEnabled()) { + log.warn("Deprecated tagValue usage: " + value); + } + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe tags + return false; + } + } + + ObjectModelImpl modelImpl = (ObjectModelImpl) model; + if (tag.equals(EugeneTagValues.TAG_VERSION)) { + + // push directly the version in the model version property + modelImpl.setVersion(value); + } + if (verbose) { + log.info("model tag value imported " + tag + " → " + value); + } + modelImpl.addTagValue(tag, value); + + return safe; + + } + + @Override + public boolean onModelStereotypeFound(String stereotype) { + + boolean safe = false; + + try { + stereotypeDefinitionProvider.validate(stereotype, ObjectModel.class); + safe = true; + } catch (StereotypeNotFoundException e) { + + String message = "Invalid model stereotype [" + stereotype + "] : the stereotype '" + stereotype + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchStereotypeTargetException e) { + String message = "Invalid model stereotype [" + stereotype + "] : this stereotype '" + stereotype + "' can not be apply on model."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if stereotype is deprecated + boolean deprecated = stereotypeDefinitionProvider.isDeprecated(stereotype); + if (deprecated) { + log.warn("Deprecated model stereotype usage: " + stereotype); + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe stereotypes + return false; + } + } + + if (verbose) { + log.info("stereotype imported " + stereotype + " → model."); + } + return safe; + } + + @Override + public boolean onPackageTagValueFound(String packageName, String tag, String value) { + + boolean safe = false; + + try { + tagValueDefinitionProvider.validate(tag, ObjectModelPackage.class); + safe = true; + } catch (TagValueNotFoundException e) { + String message = "Invalid tag value on package [" + packageName + "]: the tagvalue '" + tag + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchTagValueTargetException e) { + String message = "Invalid tag value on package [" + packageName + "]: this tagvalue '" + tag + "' can not be apply on the model."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + + } + + if (safe) { + + // test if tagValue is deprecated + boolean deprecated = tagValueDefinitionProvider.isDeprecated(tag); + if (deprecated) { + if (log.isWarnEnabled()) { + log.warn("Deprecated tagValue usage on package [" + packageName + "]: " + value); + } + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe tags + return false; + } + } + + ObjectModelPackage aPackage = model.getPackage(packageName); + if (verbose) { + log.info("imported tag value on package [" + packageName + "] → " + tag + " = " + value); + } + aPackage.addTagValue(tag, value); + return true; + } + + @Override + public boolean onPackageStereotypeFound(String packageName, String stereotype) { + + boolean safe = false; + try { + stereotypeDefinitionProvider.validate(stereotype, ObjectModelPackage.class); + safe = true; + } catch (StereotypeNotFoundException e) { + String message = "Invalid model stereotype on package [" + packageName + "]: the stereotype '" + stereotype + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchStereotypeTargetException e) { + String message = "Invalid model stereotype on package [" + packageName + "]: this stereotype '" + stereotype + "' can not be apply on package."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if tagValue is deprecated + boolean deprecated = stereotypeDefinitionProvider.isDeprecated(stereotype); + if (deprecated) { + log.warn("Deprecated stereotype usage on package [" + packageName + "]: " + stereotype); + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe stereotypes + return false; + } + } + + ObjectModelPackage omc = model.getPackage(packageName); + if (omc == null) { + + // package not found + return false; + } + + omc.addStereotype(stereotype); + + if (verbose) { + log.info("imported stereotype on package [" + packageName + "] → " + stereotype); + } + + return true; + } + + @Override + public boolean onClassTagValueFound(String className, String tag, String value) { + + boolean safe = false; + + try { + tagValueDefinitionProvider.validate(tag, ObjectModelClass.class); + safe = true; + } catch (TagValueNotFoundException e) { + + String message = "Invalid tag value on class [" + className + "]: this tagvalue '" + tag + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + + } catch (MismatchTagValueTargetException e) { + String message = "Invalid tag value on class [" + className + "]: this tagvalue '" + tag + "' can not be apply on class scope."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if tagValue is deprecated + boolean deprecated = tagValueDefinitionProvider.isDeprecated(tag); + if (deprecated) { + if (log.isWarnEnabled()) { + log.warn("Deprecated tagValue usage on class [" + className + "] : " + value); + } + } + } else { + + if (strictLoading) { + // in strict loading do not accept unsafe tags + return false; + } + } + + ObjectModelClassifier omc = getClassifier(className); + if (omc == null) { + + // classifier not found + return false; + } + + omc.addTagValue(tag, value); + + if (verbose) { + log.info("tag value imported on class [" + className + "] → " + tag + " = " + value); + } + return true; + + } + + @Override + public boolean onClassStereotypeFound(String className, String stereotype) { + + boolean safe = false; + try { + stereotypeDefinitionProvider.validate(stereotype, ObjectModelClassifier.class); + safe = true; + } catch (StereotypeNotFoundException e) { + + String message = "Invalid model stereotype on class [" + className + "]: the stereotype '" + stereotype + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchStereotypeTargetException e) { + String message = "Invalid model stereotype on class [" + className + "]: this stereotype '" + stereotype + "' can not be apply on class scope."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if stereotype is deprecated + boolean deprecated = stereotypeDefinitionProvider.isDeprecated(stereotype); + if (deprecated) { + if (log.isWarnEnabled()) { + log.warn("Deprecated stereotype usage on class [" + className + "]: " + stereotype); + } + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe stereotypes + return false; + } + } + + ObjectModelClassifier omc = getClassifier(className); + if (omc == null) { + + // classifier not found + return false; + } + + if (verbose) { + log.info("stereotype imported on class [" + className + "] → " + stereotype); + } + + return true; + + } + + @Override + public boolean onAttributeTagValueFound(String className, String attributeName, String tag, String value) { + + boolean safe = false; + + try { + tagValueDefinitionProvider.validate(tag, ObjectModelAttribute.class); + safe = true; + } catch (TagValueNotFoundException e) { + + String message = "Invalid tag value on attribute [" + className + "#" + attributeName + "]: this tagvalue '" + tag + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + + } catch (MismatchTagValueTargetException e) { + String message = "Invalid tag value on attribute [" + className + "#" + attributeName + "]: this tagvalue '" + tag + "' can not be apply on attribute scope."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if tagValue is deprecated + boolean deprecated = tagValueDefinitionProvider.isDeprecated(tag); + if (deprecated) { + if (log.isWarnEnabled()) { + log.warn("Deprecated tagValue usage on attribute [" + className + "#" + attributeName + "] : " + value); + } + } + } else { + + if (strictLoading) { + // in strict loading do not accept unsafe tags + return false; + } + } + + ObjectModelClassifier omc = getClassifier(className); + if (omc == null) { + + // classifier not found + return false; + } + + ObjectModelAttribute attribute = getAttribute(omc, attributeName); + + if (attribute == null) { + + // attribute not found + return false; + } + attribute.addTagValue(tag, value); + + if (verbose) { + log.info("tag value imported on attribute [" + className + "#" + attributeName + "] → " + tag + " = " + value); + } + return true; + + } + + @Override + public boolean onAttributeStereotypeFound(String className, String attributeName, String stereotype) { + + boolean safe = false; + try { + stereotypeDefinitionProvider.validate(stereotype, ObjectModelAttribute.class); + safe = true; + } catch (StereotypeNotFoundException e) { + + String message = "Invalid model stereotype on attribute [" + className + "#" + attributeName + "]: the stereotype '" + stereotype + "' is unknown."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } catch (MismatchStereotypeTargetException e) { + String message = "Invalid model stereotype on attribute [" + className + "#" + attributeName + "]: this stereotype '" + stereotype + "' can not be apply on attribute scope."; + if (strictLoading) { + log.error(message); + } else { + log.warn(message); + } + } + + if (safe) { + + // test if stereotype is deprecated + boolean deprecated = stereotypeDefinitionProvider.isDeprecated(stereotype); + if (deprecated) { + log.warn("Deprecated stereotype usage on attribute [" + className + "]: " + stereotype); + } + } else { + if (strictLoading) { + // in strict loading do not accept unsafe stereotypes + return false; + } + } + + ObjectModelClassifier omc = getClassifier(className); + if (omc == null) { + + // classifier not found + return false; + } + ObjectModelAttribute attribute = getAttribute(omc, attributeName); + if (attribute == null) { + + // attribute not found + return false; + } + attribute.addStereotype(stereotype); + + if (verbose) { + log.info("stereotype imported on attribute [" + className + "#" + attributeName + "] → " + stereotype); + } + + return true; + + } + + + protected ObjectModelClassifier getClassifier(String fqn) { + ObjectModelClassifier omc = model.getClassifier(fqn); + if (omc == null) { + if (log.isWarnEnabled()) { + log.warn("Could not find classifier for " + fqn); + } + return null; + } + + //todo tchemit 2010-11-25 : what does it mean ? every thing extends ObjectModelClassifierImpl + if (!(omc instanceof ObjectModelClassifierImpl)) { + // TODO il faudra avoir des methodes d'acces en Set sur l'interface pour eviter ce message + if (log.isWarnEnabled()) { + log.warn("Can't add properties to model, " + + "it's not an " + + "ObjectModelClassifierImpl : " + + omc.getQualifiedName()); + } + return null; + } + return omc; + } + + /** + * Retrieve an attribute from a {@code clazz} with its {@code name}. + * This method manage the association class case to explore participants + * attributes if needed. + * + * @param clazz where the attribute need to be find + * @param name attribute name to find + * @return the attribute found or null + */ + protected ObjectModelAttribute getAttribute(ObjectModelClassifier clazz, + String name) { + ObjectModelAttribute result = clazz.getAttribute(name); + + // Ano #619 : FD-2010-05-17 : Specific case for Association class : + // check on participant attributes + if (result == null && clazz instanceof ObjectModelAssociationClassImpl) { + if (log.isDebugEnabled()) { + log.debug("Attribute " + name + " not found from " + + clazz.getQualifiedName() + " association class. " + + "Will check participants..."); + } + ObjectModelAssociationClass assoc = (ObjectModelAssociationClass) clazz; + for (ObjectModelAttribute participant : assoc.getParticipantsAttributes()) { + if (participant.getName().equals(name)) { + result = participant; + break; + } + } + } + return result; + } +} diff --git a/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParser.java b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParser.java new file mode 100644 index 0000000..13ddfb6 --- /dev/null +++ b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParser.java @@ -0,0 +1,16 @@ +package org.nuiton.eugene.models.object.reader.extension; + +import org.nuiton.eugene.models.stereotype.InvalidStereotypeSyntaxException; +import org.nuiton.eugene.models.tagvalue.InvalidTagValueSyntaxException; + +import java.io.File; +import java.io.IOException; + +/** + * Created on 09/09/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface ModelExtensionFileParser { + void parse(File file, ModelExtensionFileParserCallback callback) throws IOException, InvalidStereotypeSyntaxException, InvalidTagValueSyntaxException; +} diff --git a/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParserCallback.java b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParserCallback.java new file mode 100644 index 0000000..66c7bba --- /dev/null +++ b/eugene/src/main/java/org/nuiton/eugene/models/object/reader/extension/ModelExtensionFileParserCallback.java @@ -0,0 +1,28 @@ +package org.nuiton.eugene.models.object.reader.extension; + +import org.nuiton.eugene.models.object.ObjectModel; + +/** + * Created on 09/09/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface ModelExtensionFileParserCallback<M extends ObjectModel> { + + boolean onModelTagValueFound(String tag, String value); + + boolean onModelStereotypeFound(String stereotype); + + boolean onPackageTagValueFound(String packageName, String tag, String value); + + boolean onPackageStereotypeFound(String packageName, String stereotype); + + boolean onClassTagValueFound(String className, String tag, String value); + + boolean onClassStereotypeFound(String className, String stereotype); + + boolean onAttributeTagValueFound(String className, String attributeName, String tag, String value); + + boolean onAttributeStereotypeFound(String className, String attributeName, String stereotype); + +} -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.