422 lines
18 KiB
Standard ML
422 lines
18 KiB
Standard ML
(*****************************************************************************
|
|
* 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
|
|
*
|
|
* 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_Logger
|
|
open Rep_Core
|
|
open Rep_OclTerm
|
|
open Rep_OclType
|
|
open Rep2String
|
|
open ModelImport
|
|
open Rep_HolOcl_Namespace
|
|
|
|
(* 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_tuples 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 _ = trace function_calls ("WFCPOG_Refine_Constraint.group_cl \n")
|
|
val _ = trace wgen ("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 _ = trace function_ends ("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 _ = trace function_calls ("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 _ = trace function_ends ("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 _ = trace function_calls ("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 _ = trace wgen ("abstract public classes: \n")
|
|
val _ = List.map (fn a => trace wgen (" - " ^ (string_of_path (name_of a))^"\n")) abs_c
|
|
val _ = trace wgen ("map_public_classes 2 \n")
|
|
val _ = trace wgen ("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 _ = trace wgen ("concrete public classes: \n")
|
|
val _ = List.map (fn a => trace wgen (" - " ^ (string_of_path (name_of a))^"\n")) conc_c
|
|
val _ = trace wgen ("Package " ^ string_of_path (toPath) ^ " contains " ^ Int.toString (List.length(conc_c)) ^ " public classes.\n")
|
|
val _ = trace wgen ("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 _ = trace function_calls ("WFCPOG_Refine_Constraint.map_public_classes\n")
|
|
*)
|
|
in
|
|
res
|
|
end
|
|
|
|
fun map_public_ops [] = [[]]
|
|
| map_public_ops ((f,t)::tail) =
|
|
let
|
|
val _ = trace function_calls ("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 _ = trace wgen ("Number of operations of f_class(" ^ (string_of_path (name_of f)) ^ ") = " ^ Int.toString (List.length(f_ops)) ^ "\n")
|
|
val _ = trace wgen ("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 _ = trace function_ends ("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 _ = trace function_calls ("WFCPOG_Refine_Constrain.map_types\n")
|
|
val _ = trace wgen ("map_types: f_cl = " ^ string_of_path (name_of h1) ^ "\n")
|
|
val _ = trace wgen ("map_types: t_cl = " ^ string_of_path (name_of h2) ^ "\n")
|
|
val _ = trace wgen ("map_types: f_op = " ^ name_of_op h3 ^ "\n")
|
|
val _ = trace wgen ("map_types: t_op = " ^ name_of_op h4 ^ "\n")
|
|
(* classifier of return type *)
|
|
(* TODO: remove next trace lines *)
|
|
val _ = trace wgen ("Length of model: " ^ Int.toString (List.length(#1 model))^ ".\n")
|
|
val ret_fC = class_of_type (#result (h3)) model
|
|
val _ = trace wgen ("map_types 2 \n")
|
|
(* name of classifier of return type *)
|
|
val ret_namefC = name_of ret_fC
|
|
val _ = trace wgen ("map_types_3: " ^ string_of_path (ret_namefC) ^ "\n")
|
|
val _ = trace wgen ("map_types_4: " ^ string_of_path fP ^ "\n")
|
|
(* relative path of return type *)
|
|
val new_path = substitute_package fP tP ret_namefC
|
|
val _ = trace wgen ("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 _ = trace wgen ("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 _ = trace wgen ("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 _ = trace wgen ("map_types_8: \n")
|
|
val res = (true)::(map_types tail fP tP model)
|
|
val _ = trace function_ends ("WFCPOG_Refine_Constrain.map_types\n")
|
|
in
|
|
res
|
|
end
|
|
|
|
fun check_syntax_help (model:Rep.Model as (clist,alist)) fromPath toPath =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.check_syntax_help\n")
|
|
(* check public classes of the two packages *)
|
|
val x = map_public_classes fromPath toPath model
|
|
val _ = trace wgen ("check syntax 2 \n")
|
|
(* check public methods of the public classes *)
|
|
val y = List.concat (map_public_ops x)
|
|
val _ = trace wgen ("check syntax 3 \n")
|
|
(* check types of the public operations of public classes *)
|
|
val z = map_types y fromPath toPath model
|
|
val _ = trace wgen ("check syntax 4 \n")
|
|
val res = List.all (fn a => a) z
|
|
val _ = trace function_ends ("WFCPOG_Refine_Constraint.check_syntax_help\n")
|
|
in
|
|
res
|
|
end
|
|
|
|
|
|
|
|
fun check_syntax wfpo (model:Rep.Model as (clist,alist)) =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.check_syntax\n")
|
|
val data = WFCPOG_RFM_Data.get wfpo
|
|
val _ = trace wgen (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 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 _ = trace function_ends ("WFCPOG_Refine_Constraint.check_syntax\n")
|
|
in
|
|
check
|
|
end
|
|
|
|
fun get_holocl_operation var_name oper class model =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.get_holocl_operation\n")
|
|
(** use Rep_Encoder to get operation as HOL-OCL-Term **)
|
|
(* val term = Rep_Encoder. .... *)
|
|
val hol_name = (name_of class)@[(name_of_op oper)]
|
|
val args = List.map (fn (a,b) => (Variable(a,b),b)) (arguments_of_op oper)
|
|
val typ = type_of class
|
|
val predicate = Predicate(Variable(var_name,typ),typ,hol_name,args)
|
|
val _ = trace function_ends ("WFCPOG_Refine_Constraint.get_holocl_operation\n")
|
|
in
|
|
predicate
|
|
end
|
|
|
|
fun get_holocl_abstraction_relation abs_path conc_path class_name =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.get_holocl_abstraction_relation\n")
|
|
val predicate_name = "R_"^(string_of_path abs_path)^"_"^(string_of_path conc_path)^"_"^class_name
|
|
val dummy_term = Variable("R",DummyT)
|
|
val predicate = Predicate(dummy_term,DummyT,[predicate_name],[])
|
|
val _ = trace function_ends ("WFCPOG_Refine_Constraint.get_holocl_abstraction_relation\n")
|
|
in
|
|
predicate
|
|
end
|
|
|
|
|
|
fun refine_operation abs_oper conc_oper abs_class conc_class model =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.refine_classifier\n")
|
|
val R = get_holocl_abstraction_relation (package_of abs_class) (package_of conc_class) (List.last(name_of abs_class))
|
|
val S = get_holocl_operation (name_of_op abs_oper) abs_oper abs_class model
|
|
val T = get_holocl_operation (name_of_op conc_oper) conc_oper conc_class model
|
|
val refine = OperationCall(S,DummyT,["holOclLib","methodology","refinement","OclForwardRefinement"],[(T,DummyT),(R,DummyT)],Boolean)
|
|
val _ = trace function_ends ("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 _ = trace function_calls ("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 _ = trace function_ends ("WFCPOG_Refine_Constraint.refine_classifier\n")
|
|
in
|
|
res
|
|
end
|
|
|
|
fun refine_package abs_path conc_path (model as (clist,alist)) =
|
|
let
|
|
val _ = trace function_calls ("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 _ = trace function_ends ("WFCPOG_Refine_Constraint.refine_package\n")
|
|
in
|
|
res
|
|
end
|
|
|
|
fun generate_pos wfpo (model as (clist,alist)) =
|
|
let
|
|
val _ = trace function_calls ("WFCPOG_Refine_Constraint.generate_pos\n")
|
|
val _ = trace wgen ("remove OclLib ...\n")
|
|
val classes = removeOclLibrary clist
|
|
val _ = trace wgen ("oclLib removed ...\n")
|
|
val _ = trace wgen ("Extract args ...\n")
|
|
val rfm_args = WFCPOG_RFM_Data.get wfpo
|
|
val packages = (#rfm_tuple rfm_args)
|
|
val _ = trace wgen("Args extracted ...\n")
|
|
val res = refine_package (#1 packages) (#2 packages) model
|
|
val _ = trace function_ends ("WFCPOG_Refine_Constraint.generate_pos\n")
|
|
in
|
|
res
|
|
end
|
|
end;
|