(***************************************************************************** * su4sml --- a SML repository for managing (Secure)UML/OCL models * http://projects.brucker.ch/su4sml/ * * context_declarations.sml --- * This file is part of su4sml. * * Copyright (c) 2005-2007 ETH Zurich, Switzerland * 2008-2009 Achim D. Brucker, Germany * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************) (* $Id: context_declarations.sml 6727 2007-07-30 08:43:40Z brucker $ *) signature WFCPOG_REFINE_CONSTRAINT = sig type RFM_args structure WFCPOG_RFM_Data : sig type T = RFM_args val get : WFCPOG.wfpo -> T val put : T -> WFCPOG.wfpo -> WFCPOG.wfpo val map : (T -> T) -> WFCPOG.wfpo -> WFCPOG.wfpo end val print_refine_args : RFM_args -> string val check_syntax : WFCPOG.wfpo -> Rep.Model -> bool val generate_pos : WFCPOG.wfpo -> Rep.Model -> (Rep_OclType.Path * Rep_OclTerm.OclTerm) list end structure WFCPOG_Refine_Constraint : WFCPOG_REFINE_CONSTRAINT = struct (* su4sml *) open Rep_Helper open Rep_Core open Rep_OclTerm open Rep_OclType open Rep2String open ModelImport open Rep_HolOcl_Namespace open Rep_HolOcl_Helper (* wfcpo-gen *) open WFCPOG_Library exception ClassGroupError of Rep_Core.Classifier list * string exception OpGroupError of Rep_Core.operation list * string type RFM_args = { key : int, rfm_tuple : (Rep_OclType.Path * Rep_OclType.Path) } structure WFCPOG_RFM_Data = WFCPOG_DataFun (struct type T = RFM_args; val empty = ({key=10,rfm_tuple=([]:Path,[]:Path)}); fun copy T = T; fun extend T = T; end); fun print_refine_args (args:RFM_args) = let val tuple = (#rfm_tuple args) in (String.concat ["Refine rmf_tuple with args: abstract package = ",(string_of_path (#1 tuple)),", concrete package = ",(string_of_path (#2 tuple)),".\n"]) end fun rm x [] = [] | rm x [b] = if (x = b) then [] else [b] | rm x (h::tail) = if (x = h) then (rm x tail) else (h::(rm x tail)) fun group_cl [] [] = [] | group_cl [] toC = [] | group_cl FromC [] = let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "Classifiers " ^(String.concat (List.map (fn a => ((string_of_path (name_of a))^", ")) FromC))^" of abstract package have no corresponding classifiers in concrete package.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end | group_cl (h1::t1) list = let val _ = Logger.info ("WFCPOG_Refine_Constraint.group_cl \n") val _ = Logger.debug1 ("Class: " ^ string_of_path (name_of h1) ^ "\n") val x = List.filter (fn a => ((List.last (name_of a)) = (List.last (name_of h1)))) list val res = case (List.length(x)) of 0 => let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "Classifier " ^ (string_of_path (name_of h1)) ^ " of abstract package has no corresponding classifier in concrete package.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end | 1 => (h1,hd(x))::(group_cl t1 (rm (hd(x)) list)) | x => let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "Something extremely strange happened. It seemed that the concrete package has two classifiers with the same name!. \nPLEASE CHECK THE CLASSIFIERS OF THE CONCRETE PACKAGE FOR THE OCCURENCE OF DUPLICATES.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end val _ = Logger.info ("WFCPOG_Refine_Constraint.group_cl \n") in res end fun group_op class_name [] [] = [] | group_op class_name fromOps [] = let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "The abstract classifier "^class_name^" its operations " ^(String.concat (List.map (fn a => ((name_of_op a)^", ")) fromOps))^" have no corresponding operations in the concrete classifier.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end | group_op class_name [] toOps = [] | group_op class_name ((h1:operation)::t1) list = let (* TODO: Check also signature because of the overloaded operations! *) val _ = Logger.info ("WFCPOG_Refine_Constraint.group_op \n") val x = (List.filter (fn a => ((name_of_op a) = (name_of_op h1))) list) val res = case (List.length(x)) of 0 => let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "The abstract classifier "^class_name^" its operation " ^(name_of_op h1)^ " has no corresponding operation in the concrete classifier.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end | 1 => (h1,List.hd(x))::(group_op class_name t1 (rm (List.hd(x)) list)) | x => let val s1 = "SYNTAX ERROR: OO Refinement syntax check\n\n" val s2 = "Something extremely strange happened. It seemed that the classifier "^class_name^"has two operations with the same name!. \nPLEASE CHECK THE CLASSIFIERS OF THE CONCRETE PACKAGE FOR THE OCCURENCE OF DUPLICATES.\n" in raise WFCPOG.WFC_FailedMessage (s1^s2) end val _ = Logger.info ("WFCPOG_Refine_Constraint.group_op \n") in res end (* RETURN: (Classifier * Classifer) list *) fun map_public_classes fromPath toPath (model as (clist,alist)) = let val _ = Logger.info ("WFCPOG_Refine_Constraint.map_public_classes\n") val abs_c = List.filter (is_visible_cl) (List.filter (fn a => if (package_of a = fromPath) then true else false) (clist)) val _ = Logger.debug1 ("abstract public classes: \n") val _ = List.map (fn a => Logger.debug1 (" - " ^ (string_of_path (name_of a))^"\n")) abs_c val _ = Logger.debug1 ("map_public_classes 2 \n") val _ = Logger.debug1 ("Package " ^ string_of_path (fromPath) ^ " contains " ^ Int.toString (List.length(abs_c)) ^ " public classes.\n") val conc_c = List.filter (is_visible_cl) (List.filter (fn a => if (package_of a = toPath) then true else false) (clist)) val _ = Logger.debug1 ("concrete public classes: \n") val _ = List.map (fn a => Logger.debug1 (" - " ^ (string_of_path (name_of a))^"\n")) conc_c val _ = Logger.debug1 ("Package " ^ string_of_path (toPath) ^ " contains " ^ Int.toString (List.length(conc_c)) ^ " public classes.\n") val _ = Logger.debug1 ("map_public_classes 3 \n") val res = group_cl abs_c conc_c (* handle WFCPOG.WFC_FailedMessage s => let val s1 = ("SYNTAX ERROR: Class consistency \n\n") val s2 = ("The following public classes are not included in the refined class:\n\n") val s3 = (String.concat (List.map (fn a => (" * " ^ (string_of_path (name_of a)) ^ "\n")) clist)) in raise WFCPOG.WFC_FailedMessage (s1^s2^s3) end val _ = Logger.info ("WFCPOG_Refine_Constraint.map_public_classes\n") *) in res end fun map_public_ops [] = [[]] | map_public_ops ((f,t)::tail) = let val _ = Logger.info ("Refine_Constraint.map_public_ops\n") val f_ops = List.filter (is_visible_op) (local_operations_of f) val t_ops = List.filter (is_visible_op) (local_operations_of t) val _ = Logger.debug1 ("Number of operations of f_class(" ^ (string_of_path (name_of f)) ^ ") = " ^ Int.toString (List.length(f_ops)) ^ "\n") val _ = Logger.debug1 ("Number of operations of t_class(" ^ (string_of_path (name_of t)) ^ ") = " ^ Int.toString (List.length(t_ops)) ^ "\n") val res = [(List.map (fn (a,b) => (f,t,a,b)) (group_op (List.last (Rep_Core.name_of f)) f_ops t_ops handle OpGroupError (oplist,s) => let val s1 = ("SYNTAX ERROR: Operation consistency \n\n") val s2 = ("FromClass = " ^ (string_of_path (name_of f)) ^ "\n") val s3 = ("ToClass = " ^ (string_of_path (name_of t)) ^ "\n") val s4 = ("The following public operations are not included in the refined classes:\n\n") val s5 = (String.concat (List.map (fn a => (" * " ^ (operation2string a) ^ "\n")) oplist)) in raise WFCPOG.WFC_FailedMessage (s1^s2^s3^s4^s5) end ))] @(map_public_ops tail) val _ = Logger.info ("Refine_Constraint.map_public_op\n") in res end fun map_types [] fP tP model = [] | map_types ((h1:Classifier,h2:Classifier,h3:operation,h4:operation)::tail) fP tP model = let val _ = Logger.info ("WFCPOG_Refine_Constrain.map_types\n") val _ = Logger.debug1 ("map_types: f_cl = " ^ string_of_path (name_of h1) ^ "\n") val _ = Logger.debug1 ("map_types: t_cl = " ^ string_of_path (name_of h2) ^ "\n") val _ = Logger.debug1 ("map_types: f_op = " ^ name_of_op h3 ^ "\n") val _ = Logger.debug1 ("map_types: t_op = " ^ name_of_op h4 ^ "\n") (* classifier of return type *) (* TODO: remove next trace lines *) val _ = Logger.debug1 ("Length of model: " ^ Int.toString (List.length(#1 model))^ ".\n") val ret_fC = class_of_type (#result (h3)) model val _ = Logger.debug1 ("map_types 2 \n") (* name of classifier of return type *) val ret_namefC = name_of ret_fC val _ = Logger.debug1 ("map_types_3: " ^ string_of_path (ret_namefC) ^ "\n") val _ = Logger.debug1 ("map_types_4: " ^ string_of_path fP ^ "\n") (* relative path of return type *) val new_path = substitute_package fP tP ret_namefC val _ = Logger.debug1 ("map_types_5: name of return type: " ^ string_of_path (ret_namefC) ^ "\n") val c1 = class_of (new_path) (model) handle _ => let val s1 = ("\n\n#####################################################################\n") val s2 = ("#####################################################################\n\n") val s3 = ("SYNTAX ERROR: Map types \n\n") val s4 = ("The return type of the operation " ^ (operation2string h3) ^ " is inconsistent.\n") val s4 = ("The refining package has no corresponding class.\n") val s5 = ("Existing FromClass = " ^ (string_of_path (name_of h1)) ^ "\n") val s6 = ("Inexisting ToClass = " ^ (string_of_path (name_of h2)) ^ "\n") in raise WFCPOG.WFC_FailedMessage (s1^s2^s3^s4^s5^s6) end (* name of the arguments *) val _ = Logger.debug1 ("map_types_6: " ^ string_of_path (name_of c1) ^ "\n") val arg_class_name1 = List.map (fn (a,b) => (name_of (class_of_type b model))) (arguments_of_op (h3)) val _ = Logger.debug1 ("map_types_7: \n") val c2 = List.map (fn a => let val rel_path = substitute_package fP tP a in class_of (rel_path) (model) handle _ => let val s1 = ("\n\n########################################################\n") val s2 = ("########################################################\n\n") val s3 = ("SYNTAX ERROR: Map types \n\n") val s4 = ("One of the arguments type of the operation " ^ (operation2string h3) ^ " is inconsistent.\n") val s5 = ("The refining package has no corresponding class.\n") val s6 = ("Existing FromClass = " ^ (string_of_path (name_of h1)) ^ "\n") val s7 = ("Inexisting ToClass = " ^ (string_of_path (name_of h2)) ^ "\n") in raise WFCPOG.WFC_FailedMessage (s1^s2^s3^s4^s5^s6^s7) end end ) arg_class_name1 val _ = Logger.debug1 ("map_types_8: \n") val res = (true)::(map_types tail fP tP model) val _ = Logger.info ("WFCPOG_Refine_Constrain.map_types\n") in res end fun check_syntax_help (model:Rep.Model as (clist,alist)) fromPath toPath = let val _ = Logger.info ("WFCPOG_Refine_Constraint.check_syntax_help\n") (* check public classes of the two packages *) val x = map_public_classes fromPath toPath model val _ = Logger.debug1 ("check syntax 2 \n") (* check public methods of the public classes *) val y = List.concat (map_public_ops x) val _ = Logger.debug1 ("check syntax 3 \n") (* check types of the public operations of public classes *) val z = map_types y fromPath toPath model val _ = Logger.debug1 ("check syntax 4 \n") val res = List.all (fn a => a) z val _ = Logger.info ("WFCPOG_Refine_Constraint.check_syntax_help\n") in res end fun check_syntax wfpo (model:Rep.Model as (clist,alist)) = let val _ = Logger.info ("WFCPOG_Refine_Constraint.check_syntax\n") val data = WFCPOG_RFM_Data.get wfpo val _ = Logger.debug1 (print_refine_args data) val packages = (#rfm_tuple data) val from = (#1 packages) val to = (#2 packages) val model_packages = all_packages_of_model model val _ = Logger.debug1 ("Packages of model: "^(String.concat (List.map (fn a => ((string_of_path a)^", ")) model_packages))^".\n") val _ = Logger.debug1 ("Abstract Package = "^(string_of_path from)^", contains "^(Int.toString (List.length(from)))^" strings.\n") val _ = Logger.debug1 ("Concrete Package = "^(string_of_path to)^", contains "^(Int.toString(List.length(from)))^" strings.\n") val check = if ((member from model_packages) andalso (member to model_packages)) then check_syntax_help model from to handle WFCPOG.WFC_FailedMessage s => raise WFCPOG.WFC_FailedException (wfpo,s) else let val s1 = ("\n\n########################################################\n") val s2 = ("########################################################\n\n") val s3 = ("SYNTAX ERROR: check_syntax\n\n") val s4 = ("No classifier where found with the package name of the abstract or concrete path.\n") in raise WFCPOG.WFC_FailedException (wfpo,s1^s2^s3^s4) end val _ = Logger.info ("WFCPOG_Refine_Constraint.check_syntax\n") in check end (* fun refine_operation abs_oper conc_oper abs_class conc_class model = let val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") val state = Variable("mystate",OclState) val op_term = get_holocl_operation ("abs") abs_oper abs_class model val refine = OperationCall (op_term,DummyT,["holOclLib","Boolean","OclLocalValid"],[(state,OclState)],Boolean) val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") in (["po_refine_"^(string_of_path (name_of abs_class))^"_"^(string_of_path (name_of conc_class))^"_"^(name_of_op abs_oper)],refine) end *) fun refine_operation abs_oper conc_oper abs_class conc_class model = let val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") val R = get_holocl_abstraction_relation abs_class conc_class model val S = get_holocl_operation ("abs") abs_oper abs_class model val T = get_holocl_operation ("conc") conc_oper conc_class model val refine = OperationCall(S,DummyT,["holOclLib","methodology","refinement","OclForwardRefinement"],[(T,DummyT),(R,DummyT)],Boolean) val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") in (["po_refine_"^(string_of_path (name_of abs_class))^"_"^(string_of_path (name_of conc_class))^"_"^(name_of_op abs_oper)],refine) end fun refine_classifier abs_class conc_class model = let val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") val abs_ops = List.filter (is_visible_op) (local_operations_of abs_class) val conc_ops = List.filter (is_visible_op) (local_operations_of conc_class) val gops = group_op (List.last (Rep_Core.name_of abs_class)) abs_ops conc_ops val res = List.map (fn (a,b) => refine_operation a b abs_class conc_class model) (gops) val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_classifier\n") in res end fun refine_package abs_path conc_path (model as (clist,alist)) = let val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_package\n") val abs_classes = List.filter (fn a => (package_of a = abs_path) andalso (is_visible_cl a)) (clist) val conc_classes = List.filter (fn a => (package_of a = conc_path) andalso (is_visible_cl a)) (clist) val cl_grouped = group_cl abs_classes conc_classes val res = (List.concat (List.map (fn (a,b) => refine_classifier a b model) cl_grouped)) val _ = Logger.info ("WFCPOG_Refine_Constraint.refine_package\n") in res end fun generate_pos wfpo (model as (clist,alist)) = let val _ = Logger.info ("WFCPOG_Refine_Constraint.generate_pos\n") val _ = Logger.debug1 ("remove OclLib ...\n") val classes = removeOclLibrary clist val _ = Logger.debug1 ("oclLib removed ...\n") val _ = Logger.debug1 ("Extract args ...\n") val rfm_args = WFCPOG_RFM_Data.get wfpo val packages = (#rfm_tuple rfm_args) val _ = Logger.debug1("Args extracted ...\n") val res = refine_package (#1 packages) (#2 packages) model val _ = Logger.info ("WFCPOG_Refine_Constraint.generate_pos\n") in res end end;