001: package org.andromda.core.common;
002:
003: import java.io.BufferedReader;
004: import java.io.InputStream;
005: import java.io.InputStreamReader;
006: import java.io.StringWriter;
007: import java.util.Collection;
008: import java.util.Iterator;
009: import java.util.LinkedHashMap;
010: import java.util.Map;
011:
012: import org.andromda.core.configuration.NamespaceProperties;
013: import org.andromda.core.configuration.Namespaces;
014: import org.andromda.core.configuration.Property;
015: import org.andromda.core.mapping.Mapping;
016: import org.andromda.core.mapping.Mappings;
017: import org.apache.commons.lang.StringUtils;
018:
019: /**
020: * <p/>
021: * A class that performs the merging abilities for the AndroMDA core. </p>
022: * <p/>
023: * Merging takes place when the {@link NamespaceProperties#MERGE_MAPPINGS_URI} is found within the
024: * <code>namespace</code> and merge mappings are used to replace any matching patterns in the given <code>string</code>.
025: * </p>
026: *
027: * @author Chad Brandon
028: */
029: public class Merger {
030: /**
031: * The shared instance
032: */
033: private static final Merger instance = new Merger();
034:
035: /**
036: * Stores the cached merge mappings already found (so we don't need to reconstruct again each time).
037: */
038: private final Map mergeMappingsCache = new LinkedHashMap();
039:
040: /**
041: * Gets the shared Merger instance. Normally you'll want to retrieve the instance through this method.
042: *
043: * @return the shared instance.
044: */
045: public static Merger instance() {
046: return instance;
047: }
048:
049: /**
050: * <p>
051: * Retrieves the <em>merged</em> string. The merging takes place when
052: * the {@link NamespaceProperties#MERGE_MAPPINGS_URI}is found within the
053: * <code>namespace</code> and the merge mappings are used to replace any
054: * matching patterns in the given <code>string</code>.
055: * </p>
056: *
057: * @param string the String to be replaced
058: * @param namespace This namespace is searched when attempting to find the
059: * {@link NamespaceProperties#MERGE_MAPPINGS_URI}.
060: * @return the replaced String.
061: */
062: public String getMergedString(String string, final String namespace) {
063: // avoid any possible infinite recursion with the mergedStringCache
064: // check (may need to refactor the mergedStringCache solution)
065: if (namespace != null && string != null) {
066: final Mappings mergeMappings = this
067: .getMergeMappings(namespace);
068: if (mergeMappings != null) {
069: final Collection mappings = mergeMappings.getMappings();
070: if ((mappings != null) && !mappings.isEmpty()) {
071: for (final Iterator mappingsIterator = mappings
072: .iterator(); mappingsIterator.hasNext();) {
073: final Mapping mapping = (Mapping) mappingsIterator
074: .next();
075: final Collection froms = mapping.getFroms();
076:
077: if (froms != null && !froms.isEmpty()) {
078: for (final Iterator fromsIterator = froms
079: .iterator(); fromsIterator
080: .hasNext();) {
081: final String from = StringUtils
082: .trimToEmpty((String) fromsIterator
083: .next());
084:
085: if (StringUtils.isNotEmpty(from)) {
086: final String to = mapping.getTo() != null ? mapping
087: .getTo().trim()
088: : "";
089: string = StringUtils.replace(
090: string, from, to);
091: }
092: }
093: }
094: }
095: }
096: }
097: }
098: return string;
099: }
100:
101: /**
102: * Retrieves the <em>merged</em> string. The merging takes place when
103: * the {@link NamespaceProperties#MERGE_MAPPINGS_URI}is found within the
104: * <code>namespace</code> and the merge mappings are used to replace any
105: * matching patterns in the given <code>inputStream</code>.
106: * </p>
107: *
108: * @param inputStream the InputStream instance which is first converted
109: * to a String and then merged.
110: * @param namespace This namespace is searched when attempting to find the
111: * {@link NamespaceProperties#MERGE_MAPPINGS_URI}.
112: * @return the replaced String.
113: */
114: public String getMergedString(final InputStream inputStream,
115: final String namespace) {
116: try {
117: StringWriter writer = new StringWriter();
118: BufferedReader inputReader = new BufferedReader(
119: new InputStreamReader(inputStream));
120: for (int ctr = inputReader.read(); ctr != -1; ctr = inputReader
121: .read()) {
122: writer.write(ctr);
123: }
124: inputReader.close();
125: inputReader = null;
126: final String string = writer.toString();
127: writer.close();
128: writer = null;
129: return this .getMergedString(string, namespace);
130: } catch (final Exception exception) {
131: throw new MergerException(exception);
132: }
133: }
134:
135: /**
136: * Indicates whether or not the given <code>namespace</code>
137: * requires a merge.
138: * @param namespace the namespace to evaluate.
139: * @return true/false
140: */
141: public boolean requiresMerge(final String namespace) {
142: final Mappings mergeMappings = this .getMergeMappings(namespace);
143: return (mergeMappings != null)
144: && !mergeMappings.getMappings().isEmpty();
145: }
146:
147: /**
148: * Attempts to retrieve the Mappings instance for the given <code>mergeMappingsUri</code> belonging to the given
149: * <code>namespace</code>.
150: *
151: * @param namespace the namespace to which the mappings belong.
152: * @return the Mappings instance.
153: */
154: private Mappings getMergeMappings(final String namespace) {
155: Mappings mergeMappings = null;
156: if (StringUtils.isNotBlank(namespace)) {
157: final Property mergeMappingsUri = Namespaces.instance()
158: .getProperty(namespace,
159: NamespaceProperties.MERGE_MAPPINGS_URI,
160: false);
161: String mergeMappingsUriValue = (mergeMappingsUri != null) ? mergeMappingsUri
162: .getValue()
163: : null;
164: if (StringUtils.isNotBlank(mergeMappingsUriValue)) {
165: mergeMappings = (Mappings) this.mergeMappingsCache
166: .get(mergeMappingsUriValue);
167:
168: if (mergeMappings == null) {
169: mergeMappings = Mappings
170: .getInstance(mergeMappingsUriValue);
171: this.mergeMappingsCache.put(mergeMappingsUriValue,
172: mergeMappings);
173: }
174: }
175: }
176: return mergeMappings;
177: }
178: }
|