001: //Copyright (c) Hans-Joachim Daniels 2005
002: //
003: //This program is free software; you can redistribute it and/or modify
004: //it under the terms of the GNU General Public License as published by
005: //the Free Software Foundation; either version 2 of the License, or
006: //(at your option) any later version.
007: //
008: //This program is distributed in the hope that it will be useful,
009: //but WITHOUT ANY WARRANTY; without even the implied warranty of
010: //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: //GNU General Public License for more details.
012: //
013: //You can either finde the file LICENSE or LICENSE.TXT in the source
014: //distribution or in the .jar file of this application
015:
016: package de.uka.ilkd.key.ocl.gf;
017:
018: import java.util.Hashtable;
019: import java.util.logging.Level;
020: import java.util.logging.Logger;
021:
022: /**
023: * @author daniels
024: *
025: * An object of this class manages a bunch of printlines which is comprised of
026: * storage and retrieval. Also giving the subcategory shortnames their long
027: * counterpart is done here.
028: */
029: class PrintnameManager {
030: /**
031: * This constructor is a bit of a hack.
032: * It puts the \%SELF subcat into this.printnames.
033: * This subcat does not appear in the grammars and thus is
034: * introduced here. If it is defined there although, this
035: * definition is used. So it does not hurt.
036: */
037: public PrintnameManager() {
038: this .subcatNames
039: .put(
040: SELF_SUBCAT,
041: "properties of self\\$shortcuts to the properties of self, that have a fitting type");
042: }
043:
044: /**
045: * The name of the subcat, that is used for the easy property access
046: * of self.
047: */
048: static final String SELF_SUBCAT = "\\%SELF";
049:
050: private static Logger logger = Logger.getLogger(Printname.class
051: .getName());
052:
053: protected final static String frontMatter = "printname fun ";
054:
055: /**
056: * The hashmap for the names of the sub categories,
057: * with the shortname starting with '%' as the key.
058: * It is important that all Printnames of one session share the same
059: * instance of Hashtable here.
060: * This field is not static because there can be several instances of
061: * the editor that shouldn't interfere.
062: */
063: protected final Hashtable subcatNames = new Hashtable();
064:
065: /**
066: * contains all the Printnames with the fun names as keys
067: */
068: protected final Hashtable printnames = new Hashtable();
069:
070: /**
071: * processes a line from the "gf pg -printer=printnames" command
072: * @param line the read line from GF
073: * Should look like
074: * printname fun neq = "<>," ++ ("parametrized" ++ ("disequality$to" ++ ("compare" ++ ("two" ++ ("instances" ++ ("on" ++ ("a" ++ ("specific" ++ "type%COMP"))))))))
075: * and needs to get like
076: * printname fun neq = "<>, parametrized disequality$to compare two instances on a specific type%COMP"
077: * @param funTypes contains funs, mapped to their types
078: */
079: public void addNewPrintnameLine(String line, Hashtable funTypes) {
080: line = removePluses(line);
081:
082: //remove "printname fun " (the frontMatter)
083: final int index = line.indexOf(frontMatter);
084: line = line.substring(index + frontMatter.length()).trim();
085:
086: //extract fun name
087: final int endFun = line.indexOf(' ');
088: final String fun = line.substring(0, endFun);
089: final String type = (String) funTypes.get(fun);
090: //extract printname
091: String printname = line.substring(line.indexOf('"') + 1, line
092: .lastIndexOf('"'));
093:
094: addNewPrintname(fun, printname, type);
095: }
096:
097: /**
098: * The printname printer of pg spits out no String, but a wrapping of
099: * small Strings conjoined with ++ which includes lots of parantheses.
100: * @param line The GF line from pg -printer=printnames
101: * @return a String representing the actual printname without the clutter
102: */
103: protected static String removePluses(String line) {
104: line = line.replaceAll("\"\\)*\\s*\\+\\+\\s*\\(*\"", " ");
105: int index = line.lastIndexOf('"');
106: line = line.substring(0, index + 1);
107: return line;
108: }
109:
110: /**
111: * Constructs the actual printname and puts it into printnames
112: * @param myFun the GF abstract fun name
113: * @param myPrintname the printname given by GF
114: */
115: protected void addNewPrintname(String myFun, String myPrintname,
116: String type) {
117: if (logger.isLoggable(Level.FINER)) {
118: logger.finer("addNewPrintname, myFun = '" + myFun
119: + "' , myPrintname = '" + myPrintname + "'");
120: }
121: Printname printname = new Printname(myFun, myPrintname,
122: this .subcatNames, type);
123: if (logger.isLoggable(Level.FINER)) {
124: logger.finer("printname = '" + printname + "'");
125: }
126: this .printnames.put(myFun, printname);
127: }
128:
129: /**
130: * looks for the Printname corresponding to the given fun.
131: * If the fun is qualified with a module and no Printname
132: * is found with module, another lookup without the module part
133: * is made.
134: * @param myFun the GF abstract fun name (with or without qualification)
135: * @return the corresponding Printname iff that one exists, null otherwise
136: */
137: public Printname getPrintname(String myFun) {
138: Printname result = null;
139: if (this .printnames.containsKey(myFun)) {
140: result = (Printname) this .printnames.get(myFun);
141: } else {
142: int index = myFun.indexOf('.');
143: if (index > -1) {
144: //a valid fun name must not be empty
145: String fun = myFun.substring(index + 1);
146: if (printnames.containsKey(fun)) {
147: result = (Printname) this .printnames.get(fun);
148: }
149: }
150: }
151: if (result == null) {
152: //?n indicates that myFun is a metavariable of GF,
153: // which does not occur in the refinement menu.
154: // if that is not wanted, don't call this method!
155: if (!myFun.startsWith("?")) {
156: logger.fine("no printname for '" + myFun
157: + "', pretend that it is a bound variable");
158: return new Printname(myFun);
159: }
160: }
161: return result;
162: }
163:
164: /**
165: * looks up the full name for the subcategory name shortname.
166: * This is the %SOMETHING from the printname.
167: * @param shortname The subcat name which should get expanded
168: * @return the corresponding full name, maybe null!
169: */
170: public String getFullname(String shortname) {
171: String result = (String) this .subcatNames.get(shortname);
172: return result;
173: }
174:
175: public static void main(String[] args) {
176: String a = "printname fun stringLiteral = \"arbitrary\" ++ (\"String$click\" ++ (\"read\" ++ (\"and\" ++ (\"enter\" ++ (\"the\" ++ (\"String\" ++ (\"in\" ++ (\"the\" ++ (\"dialog\" ++ (\"TODO%STRING(String\" ++ \"operations)\"))))))))))";
177: System.out.println(a);
178: System.out.println(removePluses(a));
179: a = "printname fun count = \"count\" ++ (\"the\" ++ (\"occurances\" ++ (\"of\" ++ (\"an\" ++ (\"object\" ++ (\"in\" ++ (\"the\" ++ \"collection.\")))))))++ (\"%COLL\" ++ (\"#collElemType\" ++ (\"The\" ++ (\"official\" ++ (\"element\" ++ (\"type\" ++ (\"of\" ++ (\"<i>coll</i>.<br>That\" ++ (\"is,\" ++ (\"the\" ++ (\"parameter\" ++ (\"type\" ++ (\"of\" ++ \"<i>coll</i>\")))))))))))++ (\"#set\" ++ (\"The\" ++ (\"Set\" ++ (\"in\" ++ (\"which\" ++ (\"occurances\" ++ (\"of\" ++ (\"<i>elem</i>\" ++ (\"are\" ++ (\"to\" ++ (\"be\" ++ \"counted.\")))))))))) ++ (\"#elem\" ++ (\"The\" ++ (\"instance\" ++ (\"of\" ++ (\"which\" ++ (\"the\" ++ (\"occurances\" ++ (\"in\" ++ (\"<i>coll</i>\" ++ (\"are\" ++ \"counted.\")))))))))))))";
180: System.out.println(a);
181: System.out.println(removePluses(a));
182: }
183:
184: }
|